···11+## 0.3.0 (2019-04-20)
22+33+* S.union and S.merge could invalidate the invariant:
44+ foreach k \in m . m[k] = (key, value) /\ k = key
55+ which could lead to assertion fail in find
66+* The signatures uses semi-explicit polymorphism with a record type:
77+ * S.equal : { f : 'a key -> 'a -> 'a -> bool } -> t -> t -> bool
88+ * S.merge : { f : 'a key -> 'a option -> 'a option -> 'a option } -> t -> t -> t
99+ * S.union : { f : 'a key -> 'a -> 'a -> 'a option } -> t -> t -> t
1010+ * new function S.map : { f : 'a key -> 'a -> 'a } -> t -> t
1111+* Interface duplication for "bindings" and "value" were removed:
1212+ S.findb, S.getb, S.addb, S.addb_unless_bound no longer exist,
1313+ use S.find, S.get, S.add, S.add_unless_bound instead.
1414+* The pretty-printer S.pp was removed, and K.pp is no longer required! S.pp is:
1515+ let pp ppf = M.iter (fun (M.B (k, v)) -> Fmt.pf ppf (K.pp k) v)
1616+* no more Fmt dependency
1717+* added some initial tests
1818+1919+## 0.2.1 (2019-02-16)
2020+2121+* move build system to dune
2222+2323+## 0.2.0 (2018-06-24)
2424+2525+* New function `update`.
2626+* New function `add_unless_bound` and `addb_unless_bound`.
2727+* Replace `type v = V : 'a key * 'a -> v` by `type b = B : 'a key * 'a -> b`.
2828+* Renamed functions ending with `v` to `b`
2929+3030+## 0.1.0 (2018-06-16)
3131+3232+* Initial release
+16
vendor/opam/gmap/LICENSE.md
···11+(*
22+ * Copyright (c) 2017 2018 Hannes Mehnert <hannes@mehnert.org>
33+ *
44+ * Permission to use, copy, modify, and distribute this software for any
55+ * purpose with or without fee is hereby granted, provided that the above
66+ * copyright notice and this permission notice appear in all copies.
77+ *
88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1515+ *
1616+ *)
+65
vendor/opam/gmap/README.md
···11+## Gmap - heterogenous maps over a GADT
22+33+%%VERSION%%
44+55+Gmap exposes the functor `Make` which takes a key type (a
66+[GADT](https://en.wikipedia.org/wiki/Generalized_algebraic_data_type) 'a key)
77+and outputs a type-safe Map where each 'a key is associated with a 'a value.
88+This removes the need for additional packing. It uses OCaml's stdlib
99+[Map](http://caml.inria.fr/pub/docs/manual-ocaml/libref/Map.html) data
1010+structure.
1111+1212+```OCaml
1313+type _ key =
1414+ | I : int key
1515+ | S : string key
1616+1717+module K = struct
1818+ type 'a t = 'a key
1919+2020+ let compare : type a b. a t -> b t -> (a, b) Gmap.Order.t = fun t t' ->
2121+ let open Gmap.Order in
2222+ match t, t' with
2323+ | I, I -> Eq | I, _ -> Lt | _, I -> Gt
2424+ | S, S -> Eq
2525+end
2626+2727+module M = Gmap.Make(K)
2828+2929+3030+let () =
3131+ let m = M.empty in
3232+ ...
3333+ match M.find I m with
3434+ | Some x -> Printf.printf "got %d\n" x
3535+ | None -> Printf.printf "found nothing\n"
3636+```
3737+3838+This is already an exhaustive pattern match: there is no need for another case
3939+(for the constructor `S`) since the type system knows that looking for `I` will
4040+result in an `int`.
4141+4242+Motivation came from parsing of protocols which usually specify optional values
4343+and extensions via a tag-length-value (TLV) mechanism: for a given tag the
4444+structure of value is different - see for example IP options, TCP options, DNS
4545+resource records, TLS hello extensions, etc.
4646+4747+Discussing this problem with Justus Matthiesen during summer 2017, we came up
4848+with this design. Its main difference to Daniel C. Bünzli's
4949+[hmap](http://erratique.ch/software/hmap) is that in gmap the key-value GADT
5050+type must be provided when instantiating the functor. In hmap, keys are created
5151+dynamically.
5252+5353+## Documentation
5454+5555+[](https://travis-ci.org/hannesm/gmap)
5656+5757+[API documentation](https://hannesm.github.io/gmap/doc/) is available online.
5858+5959+## Installation
6060+6161+You need [opam](https://opam.ocaml.org) installed on your system. The command
6262+6363+`opam install gmap`
6464+6565+will install this library.
···11+(* (c) 2017, 2018 Hannes Mehnert, all rights reserved *)
22+33+(* this code wouldn't exist without Justus Matthiesen, thanks for the help! *)
44+55+module Order = struct
66+ type (_,_) t =
77+ | Lt : ('a, 'b) t
88+ | Eq : ('a, 'a) t
99+ | Gt : ('a, 'b) t
1010+end
1111+1212+module type KEY = sig
1313+ type _ t
1414+ val compare : 'a t -> 'b t -> ('a, 'b) Order.t
1515+end
1616+1717+module type S = sig
1818+ type 'a key
1919+ type t
2020+2121+ val empty : t
2222+ val singleton : 'a key -> 'a -> t
2323+ val is_empty : t -> bool
2424+ val cardinal : t -> int
2525+ val mem : 'a key -> t -> bool
2626+ val find : 'a key -> t -> 'a option
2727+ val get : 'a key -> t -> 'a
2828+ val add_unless_bound : 'a key -> 'a -> t -> t option
2929+ val add : 'a key -> 'a -> t -> t
3030+ val remove : 'a key -> t -> t
3131+ val update : 'a key -> ('a option -> 'a option) -> t -> t
3232+3333+ type b = B : 'a key * 'a -> b
3434+3535+ val min_binding : t -> b option
3636+ val max_binding : t -> b option
3737+ val any_binding : t -> b option
3838+ val bindings : t -> b list
3939+4040+ type eq = { f : 'a . 'a key -> 'a -> 'a -> bool }
4141+ val equal : eq -> t -> t -> bool
4242+4343+ type mapper = { f : 'a. 'a key -> 'a -> 'a }
4444+ val map : mapper -> t -> t
4545+4646+ val iter : (b -> unit) -> t -> unit
4747+ val fold : (b -> 'a -> 'a) -> t -> 'a -> 'a
4848+ val for_all : (b -> bool) -> t -> bool
4949+ val exists : (b -> bool) -> t -> bool
5050+ val filter : (b -> bool) -> t -> t
5151+ type 'a fold2 = { f : 'b. 'b key -> 'b option -> 'b option -> 'a -> 'a }
5252+ val fold2 : 'a fold2 -> t -> t -> 'a -> 'a
5353+ type merger = { f : 'a. 'a key -> 'a option -> 'a option -> 'a option }
5454+ val merge : merger -> t -> t -> t
5555+ type unionee = { f : 'a. 'a key -> 'a -> 'a -> 'a option }
5656+ val union : unionee -> t -> t -> t
5757+end
5858+5959+module Make (Key : KEY) : S with type 'a key = 'a Key.t = struct
6060+ type 'a key = 'a Key.t
6161+ type k = K : 'a key -> k
6262+ type b = B : 'a key * 'a -> b
6363+6464+ module M = Map.Make(struct
6565+ type t = k
6666+ let compare (K a) (K b) = match Key.compare a b with
6767+ | Order.Lt -> -1 | Order.Eq -> 0 | Order.Gt -> 1
6868+ end)
6969+7070+ type t = b M.t
7171+7272+ let empty = M.empty
7373+ let singleton k v = M.singleton (K k) (B (k, v))
7474+7575+ let is_empty = M.is_empty
7676+ let mem k m = M.mem (K k) m
7777+7878+ let add k v m = M.add (K k) (B (k, v)) m
7979+8080+ let add_unless_bound k v m = if mem k m then None else Some (add k v m)
8181+8282+ let remove k m = M.remove (K k) m
8383+8484+ let get : type a. a key -> t -> a = fun k m ->
8585+ match M.find (K k) m with
8686+ | B (k', v) ->
8787+ (* TODO this compare (and further below similar ones) is only needed for
8888+ the type checker (to get the k = k' proof), because the invariant
8989+ foreach k . t [K k] = B (k', v) -> k = k' is preserved by this library
9090+9191+ it could be replaced by:
9292+ - Obj.magic
9393+ - vendor and slight modification of Stdlib.Map
9494+ - using integers as key -> compare can be a single instruction
9595+ Stay better safe than sorry (at least for now) *)
9696+ match Key.compare k k' with
9797+ | Order.Eq -> v
9898+ | _ -> assert false
9999+100100+ let find : type a. a key -> t -> a option = fun k m ->
101101+ try Some (get k m) with Not_found -> None
102102+103103+ let update k f m =
104104+ match f (find k m) with
105105+ | None -> remove k m
106106+ | Some v -> add k v m
107107+108108+ let any_binding m = try Some (snd (M.choose m)) with Not_found -> None
109109+ let min_binding m = try Some (snd (M.min_binding m)) with Not_found -> None
110110+ let max_binding m = try Some (snd (M.max_binding m)) with Not_found -> None
111111+ let bindings m = snd (List.split (M.bindings m))
112112+113113+ let cardinal m = M.cardinal m
114114+115115+ let for_all p m = M.for_all (fun _ b -> p b) m
116116+ let exists p m = M.exists (fun _ b -> p b) m
117117+118118+ let iter f m = M.iter (fun _ b -> f b) m
119119+ let fold f m acc = M.fold (fun _ b acc -> f b acc) m acc
120120+ let filter p m = M.filter (fun _ b -> p b) m
121121+122122+ type mapper = { f : 'a. 'a key -> 'a -> 'a }
123123+ let map f m = M.map (fun (B (k, v)) -> B (k, f.f k v)) m
124124+125125+ type merger = { f : 'a. 'a key -> 'a option -> 'a option -> 'a option }
126126+127127+ let merge f m m' =
128128+ let callf : type x y. x key -> x option -> y key -> y option -> b option =
129129+ fun k v k' v' ->
130130+ (* see above comment in get about this useless Key.compare *)
131131+ match Key.compare k k' with
132132+ | Order.Eq ->
133133+ (match f.f k v v' with
134134+ | None -> None
135135+ | Some v'' -> Some (B (k, v'')))
136136+ | _ -> assert false
137137+ in
138138+ M.merge (fun (K key) b b' ->
139139+ match b, b' with
140140+ (* Map.merge never calls f None None, just for the types *)
141141+ | None, None -> None
142142+ | None, Some B (k', v') -> callf key None k' (Some v')
143143+ | Some B (k, v), None -> callf k (Some v) key None
144144+ | Some B (k, v), Some B (k', v') -> callf k (Some v) k' (Some v')
145145+ )
146146+ m m'
147147+148148+ type 'a fold2 = { f : 'b. 'b key -> 'b option -> 'b option -> 'a -> 'a }
149149+150150+ let fold2 f m m' acc =
151151+ let local = ref acc in
152152+ let f k v1 v2 = local := f.f k v1 v2 !local; None in
153153+ ignore (merge { f } m m');
154154+ !local
155155+156156+ type unionee = { f : 'a. 'a key -> 'a -> 'a -> 'a option }
157157+ let union f m m' =
158158+ M.union
159159+ (fun (K k) (B (k', v)) (B (k'', v')) ->
160160+ (* see above comment about compare *)
161161+ match Key.compare k k', Key.compare k k'' with
162162+ | Order.Eq, Order.Eq ->
163163+ (match f.f k v v' with None -> None | Some v'' -> Some (B (k, v'')))
164164+ | _ -> assert false)
165165+ m m'
166166+167167+ type eq = { f : 'a . 'a key -> 'a -> 'a -> bool }
168168+ let equal cmp m m' =
169169+ M.equal (fun (B (k, v)) (B (k', v')) ->
170170+ (* see above comment about compare *)
171171+ match Key.compare k k' with
172172+ | Order.Eq -> cmp.f k v v'
173173+ | _ -> assert false)
174174+ m m'
175175+end
+236
vendor/opam/gmap/gmap.mli
···11+(* (c) 2017, 2018 Hannes Mehnert, all rights reserved *)
22+(* this code wouldn't exist without Justus Matthiesen, thanks for the help! *)
33+44+(** Heterogenous maps over a GADT.
55+66+ The motivation for this library originated in the area of parsing binary
77+ network protocols, which often contain options and extensions in the form of
88+ tag, length, value encodings: the set of tags and corresponding values is
99+ specified in some Internet standard, and later extended by using a global
1010+ registry. Examples are IP options, TCP options, DNS resource records, TLS
1111+ hello extensions, X.509v3 extensions, ... These extension mechanisms usually
1212+ include the invariant that each tag may only be present once.
1313+1414+ A more naive approach is to use a variant type of all known tag-value
1515+ combinations and storing these in an association list while parsing, but
1616+ verifying the uniqueness invariant takes quadratic ([O(n^2)]) time, and
1717+ retrieving a specific option is only doable in linear [O(n)] time.
1818+ Additionally, packing and unpacking is required with the variant type
1919+ solution.
2020+2121+ In gmap, {{:https://en.wikipedia.org/wiki/Generalized_algebraic_data_type}GADTs}
2222+ are used to provide key-dependent value types: each GADT constructor carries
2323+ their value type. The underlying storage mechanism uses OCaml's stdlib
2424+ {{:http://caml.inria.fr/pub/docs/manual-ocaml/libref/Map.html}Map} type:
2525+ Lookup takes [O(log n)] time. The above mentioned uniqueness invariant can
2626+ be preserved while constructing the gmap if for insertion into the map only
2727+ {!S.update} and {!S.add_unless_bound} are used ({!S.add} replaces the
2828+ existing binding if present).
2929+3030+ A small example:
3131+3232+{[
3333+type _ key =
3434+ | I : int key
3535+ | S : string key
3636+3737+module K = struct
3838+ type 'a t = 'a key
3939+4040+ let compare : type a b. a t -> b t -> (a, b) Gmap.Order.t = fun t t' ->
4141+ let open Gmap.Order in
4242+ match t, t' with
4343+ | I, I -> Eq | I, _ -> Lt | _, I -> Gt
4444+ | S, S -> Eq
4545+end
4646+4747+module GM = Gmap.Make(K)
4848+]}
4949+5050+ Using [GM] is done as follows:
5151+5252+{[
5353+match GM.find I (GM.singleton I 10) with
5454+| Some x -> x * x
5555+| None -> 0
5656+]}
5757+5858+ {e %%VERSION%% - {{:%%PKG_HOMEPAGE%% }homepage}} *)
5959+6060+(** Ordering. *)
6161+module Order : sig
6262+6363+ (** The ordering type embedding type equality for [Eq]. *)
6464+ type (_,_) t =
6565+ | Lt : ('a, 'b) t
6666+ | Eq : ('a, 'a) t
6767+ | Gt : ('a, 'b) t
6868+end
6969+7070+(** Key. *)
7171+module type KEY = sig
7272+7373+ type _ t
7474+ (** The type of a key *)
7575+7676+ val compare : 'a t -> 'b t -> ('a, 'b) Order.t
7777+ (** [compare k k'] is the total order of keys. *)
7878+end
7979+8080+(** Output signature of the functor {!Make} *)
8181+module type S = sig
8282+8383+ type 'a key
8484+ (** The type for map keys whose lookup value is ['a]. *)
8585+8686+ type t
8787+ (** The type of maps from type ['a key] to ['a]. *)
8888+8989+ (** {2 Constructors} *)
9090+9191+ val empty : t
9292+ (** [empty] is the empty map. *)
9393+9494+ val singleton : 'a key -> 'a -> t
9595+ (** [singleton key value] creates a one-element map that contains a binding
9696+ [value] for [key]. *)
9797+9898+ (** {2 Basic operations} *)
9999+100100+ val is_empty : t -> bool
101101+ (** [is_empty m] returns [true] if the map [m] is empty, [false] otherwise. *)
102102+103103+ val cardinal : t -> int
104104+ (** [cardinal m] returns the number of bindings of the map [m]. *)
105105+106106+ (** {2 Lookup operations} *)
107107+108108+ val mem : 'a key -> t -> bool
109109+ (** [mem key m] returns [true] if the map [m] contains a binding for [key]. *)
110110+111111+ val find : 'a key -> t -> 'a option
112112+ (** [find key m] returns [Some v] if the binding of [key] in [m] is [v], or
113113+ [None] if [key] is not bound [m]. *)
114114+115115+ val get : 'a key -> t -> 'a
116116+ (** [find key m] returns [v] if the binding of [key] in [m] is [v].
117117+118118+ @raise Not_found if [m] does not contain a binding for [key]. *)
119119+120120+ (** {2 Insertion and removal operations} *)
121121+122122+ val add_unless_bound : 'a key -> 'a -> t -> t option
123123+ (** [add_unless_bound key value m] returns [Some m'], a map containing the
124124+ same bindings as [m], plus a binding of [key] to [value]. Or, [None] if
125125+ [key] was already bound in [m]. *)
126126+127127+ val add : 'a key -> 'a -> t -> t
128128+ (** [add key value m] returns a map containing the same bindings as [m], plus
129129+ a binding of [key] to [value]. If [key] was already bound in [m], the
130130+ previous binding disappears. *)
131131+132132+ val remove : 'a key -> t -> t
133133+ (** [remove key m] returns a map containing the same bindings as [m], except
134134+ for [key] which is not bound in the returned map. If [key] was not bound
135135+ in [m], [m] is returned unchanged. *)
136136+137137+ val update : 'a key -> ('a option -> 'a option) -> t -> t
138138+ (** [update k f m] returns a map containing the same bindings as [m], except
139139+ for the binding [v] of [k]. Depending the value of [v], which is
140140+ [f (find k m)], the binding of [k] is added, removed, or updated. *)
141141+142142+ (** {2 Bindings} *)
143143+144144+ type b = B : 'a key * 'a -> b
145145+ (** The type for a binding: a pair containing a key and its value. *)
146146+147147+ (** {2 Selection of bindings} *)
148148+149149+ val min_binding : t -> b option
150150+ (** [min_binding m] is the minimal binding in [m], [None] if [m] is empty. *)
151151+152152+ val max_binding : t -> b option
153153+ (** [max_binding m] is the maximal binding in [m], [None] if [m] is empty. *)
154154+155155+ val any_binding : t -> b option
156156+ (** [any_binding m] is any binding in [m], [None] if [m] is empty. *)
157157+158158+ val bindings : t -> b list
159159+ (** [bindings m] returns the list of all bindings in the given map [m]. The
160160+ list is sorted with respect to the ordering over the type of the keys. *)
161161+162162+ (** {2 Higher-order functions} *)
163163+164164+ type eq = { f : 'a . 'a key -> 'a -> 'a -> bool }
165165+ (** The function type for the equal operation, using a record type for
166166+ "first-class" semi-explicit polymorphism. *)
167167+168168+ val equal : eq -> t -> t -> bool
169169+ (** [equal p m m'] tests whether the maps [m] and [m'] are equal, that is
170170+ contain equal keys and associate them with equal data. [p] is the
171171+ equality predicate used to compare the data associated with the keys. *)
172172+173173+ type mapper = { f : 'a. 'a key -> 'a -> 'a }
174174+ (** The function type for the map operation, using a record type for
175175+ "first-class" semi-explicit polymorphism. *)
176176+177177+ val map : mapper -> t -> t
178178+ (** [map f m] returns a map with the same domain as [m], where the associated
179179+ binding [b] has been replaced by the result of the application of [f] to
180180+ [b]. The bindings are passed to [f] in increasing order with respect to
181181+ the ordering over the type of the keys. *)
182182+183183+ val iter : (b -> unit) -> t -> unit
184184+ (** [iter f m] applies [f] to all bindings in [m]. The bindings are passed in
185185+ increasing order with respect to the ordering over the type of keys. *)
186186+187187+ val fold : (b -> 'a -> 'a) -> t -> 'a -> 'a
188188+ (** [fold f m acc] computes [(f bN .. (f b1 acc))], where [b1 .. bN] are the
189189+ bindings of [m] in increasing order with respect to the ordering over the
190190+ type of the keys. *)
191191+192192+ val for_all : (b -> bool) -> t -> bool
193193+ (** [for_all p m] checks if all bindings of the map [m] satisfy the predicate
194194+ [p]. *)
195195+196196+ val exists : (b -> bool) -> t -> bool
197197+ (** [exists p m] checks if at least one binding of the map [m] satisfies
198198+ [p]. *)
199199+200200+ val filter : (b -> bool) -> t -> t
201201+ (** [filter p m] returns the map with all the bindings in [m] that satisfy
202202+ [p]. *)
203203+204204+ type 'a fold2 = { f : 'b. 'b key -> 'b option -> 'b option -> 'a -> 'a }
205205+ (** The function type for the fold2 operation, using a record type for
206206+ "first-class" semi-explicit polymorphism. *)
207207+208208+ val fold2 : 'a fold2 -> t -> t -> 'a -> 'a
209209+ (** [fold2 f m m' acc] iterates over [m] and [m'], and calls [f] for each
210210+ binding in [m] or [m']. It uses [Map.merge] for the folding, but
211211+ ignores the result. *)
212212+213213+ type merger = { f : 'a. 'a key -> 'a option -> 'a option -> 'a option }
214214+ (** The function type for the merge operation, using a record type for
215215+ "first-class" semi-explicit polymorphism. *)
216216+217217+ val merge : merger -> t -> t -> t
218218+ (** [merge f m m'] computes a map whose keys is a subset of keys of [m] and
219219+ [m']. The presence of each such binding, and the corresponding value, is
220220+ determined with the function [f]. [f None None] is never called, it
221221+ directly returns [None]. *)
222222+223223+ type unionee = { f : 'a. 'a key -> 'a -> 'a -> 'a option }
224224+ (** The function type for the union operation, using a record type for
225225+ "first-class" semi-explicit polymorphism. *)
226226+227227+ val union : unionee -> t -> t -> t
228228+ (** [union f m m'] computes a map whose keys is the union of the keys of [m]
229229+ and [m']. When the same binding is defined in both maps, the function [f]
230230+ is used to combine them. *)
231231+end
232232+233233+(** Functor for heterogenous maps whose keys are provided by [Key]. *)
234234+module Make (Key : KEY) : sig
235235+ include S with type 'a key = 'a Key.t
236236+end
+29
vendor/opam/gmap/gmap.opam
···11+opam-version: "2.0"
22+maintainer: "Hannes Mehnert <hannes@mehnert.org>"
33+authors: "Hannes Mehnert <hannes@mehnert.org>"
44+license: "ISC"
55+homepage: "https://github.com/hannesm/gmap"
66+doc: "https://hannesm.github.io/gmap/doc"
77+bug-reports: "https://github.com/hannesm/gmap/issues"
88+depends: [
99+ "ocaml" {>= "4.04.2"}
1010+ "dune" {>= "1.0"}
1111+ "alcotest" {with-test}
1212+ "fmt" {with-test}
1313+]
1414+build: [
1515+ ["dune" "subst"] {dev}
1616+ ["dune" "build" "-p" name "-j" jobs]
1717+ ["dune" "runtest" "-p" name "-j" jobs] {with-test}
1818+]
1919+dev-repo: "git+https://github.com/hannesm/gmap.git"
2020+synopsis: "Heterogenous maps over a GADT"
2121+description: """
2222+Gmap exposes the functor `Make` which takes a key type (a
2323+[GADT](https://en.wikipedia.org/wiki/Generalized_algebraic_data_type) 'a key)
2424+and outputs a type-safe Map where each 'a key is associated with a 'a value.
2525+This removes the need for additional packing. It uses OCaml's stdlib
2626+[Map](http://caml.inria.fr/pub/docs/manual-ocaml/libref/Map.html) data
2727+structure.
2828+"""
2929+x-maintenance-intent: [ "(latest)" ]
+160
vendor/opam/gmap/tests.ml
···11+22+type _ key =
33+ | I : int key
44+ | S : string key
55+66+let pp_m : type a . Format.formatter -> a key -> a -> unit = fun ppf k v ->
77+ match k, v with
88+ | I, x -> Fmt.pf ppf "I %d" x
99+ | S, s -> Fmt.pf ppf "S %s" s
1010+1111+let eq_m : type a. a key -> a -> a -> bool = fun k v v' ->
1212+ match k, v, v' with
1313+ | I, x, y -> x = y
1414+ | S, s, t -> String.equal s t
1515+1616+module K = struct
1717+ type 'a t = 'a key
1818+1919+ let compare : type a b. a t -> b t -> (a, b) Gmap.Order.t = fun t t' ->
2020+ let open Gmap.Order in
2121+ match t, t' with
2222+ | I, I -> Eq | I, _ -> Lt | _, I -> Gt
2323+ | S, S -> Eq
2424+end
2525+2626+module M = Gmap.Make(K)
2727+2828+let m_check =
2929+ let module M = struct
3030+ type t = M.t
3131+ let pp ppf m = M.iter (fun (M.B (k, v)) -> pp_m ppf k v) m
3232+ let equal a b = M.equal { f = eq_m } a b
3333+ end in
3434+ (module M: Alcotest.TESTABLE with type t = M.t)
3535+3636+let b_check =
3737+ let module M = struct
3838+ type t = M.b
3939+ let pp ppf (M.B (k, v)) = pp_m ppf k v
4040+ let equal (M.B (k, v)) (M.B (k', v')) = match K.compare k k' with
4141+ | Gmap.Order.Eq -> eq_m k v v'
4242+ | _ -> false
4343+ end in
4444+ (module M: Alcotest.TESTABLE with type t = M.t)
4545+4646+let empty () =
4747+ Alcotest.(check bool "empty map is empty" true (M.is_empty M.empty));
4848+ Alcotest.(check bool "mem on empty map doesn't have A" false (M.mem I M.empty));
4949+ Alcotest.(check (option int) "find on empty map doesn't have A" None
5050+ (M.find I M.empty));
5151+ Alcotest.(check (option string) "find on empty map doesn't have B" None
5252+ (M.find S M.empty));
5353+ Alcotest.(check (option b_check) "min binding is none" None
5454+ (M.min_binding M.empty));
5555+ Alcotest.(check (option b_check) "max binding is none" None
5656+ (M.max_binding M.empty));
5757+ Alcotest.(check (option b_check) "any binding is none" None
5858+ (M.any_binding M.empty));
5959+ Alcotest.(check (list b_check) "bindings is empty" []
6060+ (M.bindings M.empty))
6161+6262+let basic () =
6363+ let m = M.singleton I 5 in
6464+ Alcotest.(check bool "non-empty map is not empty" false (M.is_empty m));
6565+ Alcotest.(check int "non-empty map has cardinal 1" 1 (M.cardinal m));
6666+ Alcotest.(check bool "non-empty map has member I" true (M.mem I m));
6767+ Alcotest.(check (option int) "non-empty map finds I" (Some 5) (M.find I m));
6868+ Alcotest.check m_check "singleton and add are equivalent" m (M.add I 5 M.empty);
6969+ Alcotest.(check bool "removing I from map makes it empty" true
7070+ (M.is_empty (M.remove I m)));
7171+ Alcotest.(check bool "removing S from map makes it not empty" false
7272+ (M.is_empty (M.remove S m)));
7373+ Alcotest.check m_check "add overwrites" (M.singleton I 10) (M.add I 10 m);
7474+ Alcotest.(check (option m_check) "add_unless_bound does not overwrite" None
7575+ (M.add_unless_bound I 10 m));
7676+ Alcotest.check m_check "update updates" (M.singleton I 20)
7777+ (M.update I (fun _ -> Some 20) m);
7878+ Alcotest.(check (option b_check) "min_binding is I 5" (Some (M.B (I, 5)))
7979+ (M.min_binding m));
8080+ Alcotest.(check (option b_check) "max_binding is I 5" (Some (M.B (I, 5)))
8181+ (M.max_binding m));
8282+ Alcotest.(check (option b_check) "any_binding is I 5" (Some (M.B (I, 5)))
8383+ (M.any_binding m));
8484+ Alcotest.(check (list b_check) "bindings is [ I 5 ]" [ M.B (I, 5) ]
8585+ (M.bindings m))
8686+8787+let bad_eq_false : type a. a key -> a -> a -> bool = fun _ _ _ -> false
8888+let bad_eq_true : type a. a key -> a -> a -> bool = fun _ _ _ -> true
8989+9090+let eq () =
9191+ let m = M.singleton I 5 in
9292+ Alcotest.(check bool "m equal is ok" true (M.equal { f = eq_m } m m));
9393+ Alcotest.(check bool "m equal is ok with singleton" true
9494+ (M.equal { f = eq_m } m (M.singleton I 5)));
9595+ Alcotest.(check bool "m equal is false" false
9696+ (M.equal { f = eq_m } m M.empty));
9797+ Alcotest.(check bool "m equal is false" false
9898+ (M.equal { f = eq_m } m (M.singleton S "foo")));
9999+ Alcotest.(check bool "m equal is false" false
100100+ (M.equal { f = eq_m } m (M.singleton I 10)));
101101+ Alcotest.(check bool "m equal is false" false
102102+ (M.equal { f = eq_m } m (M.add S "foo" (M.singleton I 10))));
103103+ Alcotest.(check bool "m bad equal is always false" false
104104+ (M.equal { f = bad_eq_false } m m));
105105+ Alcotest.(check bool "m bad equal is always true" true
106106+ (M.equal { f = bad_eq_true } m m))
107107+108108+let preds () =
109109+ let m = M.singleton I 5 in
110110+ let m' = M.add S "foobar" m in
111111+ let m'' = M.singleton I 10 in
112112+ let p (M.B (k, v)) = match k with I -> v = 5 | _ -> false in
113113+ Alcotest.(check bool "for_all works" true (M.for_all p m));
114114+ Alcotest.(check bool "for_all works m'" false (M.for_all p m'));
115115+ Alcotest.(check bool "for_all works m''" false (M.for_all p m''));
116116+ Alcotest.(check bool "exists works" true (M.exists p m));
117117+ Alcotest.(check bool "exists works m'" true (M.exists p m'));
118118+ Alcotest.(check bool "exists works m''" false (M.exists p m''));
119119+ Alcotest.check m_check "filter works" m (M.filter p m);
120120+ Alcotest.check m_check "filter works m'" m (M.filter p m');
121121+ Alcotest.check m_check "filter works m''" M.empty (M.filter p m'')
122122+123123+let map () =
124124+ let m = M.singleton I 5 in
125125+ let map : type a . a key -> a -> a = fun k _v ->
126126+ match k with
127127+ | I -> 100
128128+ | S -> "Foo"
129129+ in
130130+ Alcotest.check m_check "mapped m is equal as expected"
131131+ (M.singleton I 100) (M.map { f = map } m);
132132+ Alcotest.check m_check "mapped m is equal as expected"
133133+ (M.add S "Foo" (M.singleton I 100))
134134+ (M.map { f = map } (M.add S "barf" m))
135135+136136+let l_wins : type a . a key -> a -> a -> a option = fun _ v _ -> Some v
137137+let r_wins : type a . a key -> a -> a -> a option = fun _ _ v' -> Some v'
138138+let no_wins : type a . a key -> a -> a -> a option = fun _ _ _ -> None
139139+140140+let union () =
141141+ let m = M.add I 100 (M.singleton S "foo") in
142142+ Alcotest.check m_check "union map left wins is good" m
143143+ (M.union { f = l_wins } m (M.singleton S "bar"));
144144+ Alcotest.check m_check "union map right wins is good"
145145+ (M.add I 100 (M.singleton S "bar"))
146146+ (M.union { f = r_wins } m (M.singleton S "bar"));
147147+ Alcotest.check m_check "union map right wins is good"
148148+ (M.singleton I 100)
149149+ (M.union { f = no_wins } m (M.singleton S "bar"))
150150+151151+let tests = [
152152+ "empty gmap", `Quick, empty ;
153153+ "basic gmap", `Quick, basic ;
154154+ "equality", `Quick, eq ;
155155+ "predicates", `Quick, preds ;
156156+ "map", `Quick, map ;
157157+ "union", `Quick, union ;
158158+]
159159+160160+let () = Alcotest.run "gmap tests" [ "gmap suite", tests ]