From 65aceba85e886ab02335904e353ba1200f4a6837 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Sat, 14 Jun 2014 00:11:16 +0200 Subject: [PATCH] phantom types for CCVector, for read-write and read-only vectors --- core/CCVector.ml | 34 ++++++++++-- core/CCVector.mli | 135 +++++++++++++++++++++++++--------------------- 2 files changed, 104 insertions(+), 65 deletions(-) diff --git a/core/CCVector.ml b/core/CCVector.ml index cf5de68a..115c1777 100644 --- a/core/CCVector.ml +++ b/core/CCVector.ml @@ -25,6 +25,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (** {1 Growable, mutable vector} *) +type rw = [`RW] +type ro = [`RO] + type 'a sequence = ('a -> unit) -> unit type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist] type 'a gen = unit -> 'a option @@ -34,11 +37,21 @@ type 'a printer = Buffer.t -> 'a -> unit type 'a formatter = Format.formatter -> 'a -> unit (** a vector of 'a. *) -type 'a t = { +type ('a,'mut) t = { mutable size : int; mutable vec : 'a array; } +let freeze v = { + size=v.size; + vec=v.vec; +} + +let freeze_copy v = { + size=v.size; + vec=Array.sub v.vec 0 v.size; +} + let create () = { size = 0; vec = [| |]; @@ -180,14 +193,25 @@ let copy v = { let shrink v n = if n < v.size then v.size <- n -let sort cmp v = - (* copy array (to avoid junk in it), then sort the array *) - let a = Array.sub v.vec 0 v.size in +let sort' cmp v = + (* possibly copy array (to avoid junk at its end), then sort the array *) + let a = + if Array.length v.vec = v.size then v.vec + else Array.sub v.vec 0 v.size + in Array.fast_sort cmp a; v.vec <- a +let sort cmp v = + let v' = { + size=v.size; + vec=Array.sub v.vec 0 v.size; + } in + Array.sort cmp v'.vec; + v' + let uniq_sort cmp v = - sort cmp v; + sort' cmp v; let n = v.size in (* traverse to remove duplicates. i= current index, j=current append index, j<=i. new_size is the size diff --git a/core/CCVector.mli b/core/CCVector.mli index 6981935c..4d8cd997 100644 --- a/core/CCVector.mli +++ b/core/CCVector.mli @@ -25,8 +25,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (** {1 Growable, mutable vector} *) -type 'a t -(** the type of a vector of 'a *) +type ro +type rw + +(** Mutability is [rw] (read-write) or [ro] (read-only) *) + +type ('a, 'mut) t +(** the type of a vector of elements of type ['a], with + a mutability flat ['mut] *) type 'a sequence = ('a -> unit) -> unit type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist] @@ -36,162 +42,171 @@ type 'a ord = 'a -> 'a -> int type 'a printer = Buffer.t -> 'a -> unit type 'a formatter = Format.formatter -> 'a -> unit -val create : unit -> 'a t +val freeze : ('a, _) t -> ('a, ro) t +(** Make an immutable vector (no copy! Don't use the old version)*) + +val freeze_copy : ('a, _) t -> ('a, ro) t +(** Copy the vector into an immutable version *) + +val create : unit -> ('a, rw) t (** Create a new, empty vector *) -val create_with : ?capacity:int -> 'a -> 'a t +val create_with : ?capacity:int -> 'a -> ('a, rw) t (** Create a new vector, using the given value as a filler. @param capacity the size of the underlying array {b caution}: the value will likely not be GC'd before the vector is. *) -val make : int -> 'a -> 'a t +val make : int -> 'a -> ('a, 'mut) t (** [make n x] makes a vector of size [n], filled with [x] *) -val init : int -> (int -> 'a) -> 'a t +val init : int -> (int -> 'a) -> ('a, 'mut) t (** Init the vector with the given function and size *) -val clear : 'a t -> unit +val clear : ('a, rw) t -> unit (** clear the content of the vector *) -val ensure : 'a t -> int -> unit +val ensure : ('a, rw) t -> int -> unit (** Hint to the vector that it should have at least the given capacity. Just a hint, will not be enforced if the vector is empty. *) -val is_empty : 'a t -> bool +val is_empty : ('a, _) t -> bool (** is the vector empty? *) -val push : 'a t -> 'a -> unit +val push : ('a, rw) t -> 'a -> unit (** add an element at the end of the vector *) -val append : 'a t -> 'a t -> unit +val append : ('a, rw) t -> ('a, _) t -> unit (** [append a b] adds all elements of b to a *) -val append_array : 'a t -> 'a array -> unit +val append_array : ('a, rw) t -> 'a array -> unit (** same as append, with an array *) -val append_seq : 'a t -> 'a sequence -> unit +val append_seq : ('a, rw) t -> 'a sequence -> unit (** Append content of sequence *) -val equal : 'a equal -> 'a t equal +val equal : 'a equal -> ('a,_) t equal -val compare : 'a ord -> 'a t ord +val compare : 'a ord -> ('a,_) t ord (** Lexicographic comparison *) -val pop : 'a t -> 'a option +val pop : ('a, rw) t -> 'a option (** Remove last element, or [None] *) -val pop_exn : 'a t -> 'a +val pop_exn : ('a, rw) t -> 'a (** remove last element, or raise a Failure if empty @raise Failure on an empty vector *) -val copy : 'a t -> 'a t -(** shallow copy *) +val copy : ('a,_) t -> ('a,'mut) t +(** Shallow copy (may give an immutable or mutable vector) *) -val shrink : 'a t -> int -> unit +val shrink : ('a, rw) t -> int -> unit (** shrink to the given size (remove elements above this size). Does nothing if the parameter is bigger than the current size. *) -val member : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> bool +val member : ?eq:('a -> 'a -> bool) -> 'a -> ('a, _) t -> bool (** is the element a member of the vector? *) -val sort : ('a -> 'a -> int) -> 'a t -> unit -(** sort the array in place*) +val sort : ('a -> 'a -> int) -> ('a, _) t -> ('a, 'mut) t +(** Sort the vector *) -val uniq_sort : ('a -> 'a -> int) -> 'a t -> unit +val sort' : ('a -> 'a -> int) -> ('a, rw) t -> unit +(** sort the vector in place*) + +val uniq_sort : ('a -> 'a -> int) -> ('a, rw) t -> unit (** sort the array and remove duplicates in place*) -val iter : ('a -> unit) -> 'a t -> unit +val iter : ('a -> unit) -> ('a,_) t -> unit (** iterate on the vector *) -val iteri : (int -> 'a -> unit) -> 'a t -> unit +val iteri : (int -> 'a -> unit) -> ('a,_) t -> unit (** iterate on the vector with indexes *) -val map : ('a -> 'b) -> 'a t -> 'b t +val map : ('a -> 'b) -> ('a,_) t -> ('b, 'mut) t (** map elements of the vector *) -val filter : ('a -> bool) -> 'a t -> 'a t +val filter : ('a -> bool) -> ('a,_) t -> ('a, 'mut) t (** filter elements from vector *) -val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b +val fold : ('b -> 'a -> 'b) -> 'b -> ('a,_) t -> 'b (** fold on elements of the vector *) -val exists : ('a -> bool) -> 'a t -> bool +val exists : ('a -> bool) -> ('a,_) t -> bool (** existential test *) -val for_all : ('a -> bool) -> 'a t -> bool +val for_all : ('a -> bool) -> ('a,_) t -> bool (** universal test *) -val find : ('a -> bool) -> 'a t -> 'a option +val find : ('a -> bool) -> ('a,_) t -> 'a option (** Find an element that satisfies the predicate *) -val find_exn : ('a -> bool) -> 'a t -> 'a +val find_exn : ('a -> bool) -> ('a,_) t -> 'a (** find an element that satisfies the predicate, or @raise Not_found if no element does *) -val filter_map : ('a -> 'b option) -> 'a t -> 'b t +val filter_map : ('a -> 'b option) -> ('a,_) t -> ('b, 'mut) t (** Map elements with a function, possibly filtering some of them out *) -val flat_map : ('a -> 'b t) -> 'a t -> 'b t +val flat_map : ('a -> ('b,_) t) -> ('a,_) t -> ('b, 'mut) t (** Map each element to a sub-vector *) -val flat_map' : ('a -> 'b sequence) -> 'a t -> 'b t +val flat_map' : ('a -> 'b sequence) -> ('a,_) t -> ('b, 'mut) t (** Like {!flat_map}, but using {!sequence} for intermediate collections *) -val (>>=) : 'a t -> ('a -> 'b t) -> 'b t +val (>>=) : ('a,_) t -> ('a -> ('b,_) t) -> ('b, 'mut) t -val (>|=) : 'a t -> ('a -> 'b) -> 'b t +val (>|=) : ('a,_) t -> ('a -> 'b) -> ('b, 'mut) t -val get : 'a t -> int -> 'a +val get : ('a,_) t -> int -> 'a (** access element, or @raise Failure if bad index *) -val set : 'a t -> int -> 'a -> unit +val set : ('a, rw) t -> int -> 'a -> unit (** access element, or @raise Failure if bad index *) -val rev : 'a t -> 'a t +val rev : ('a,_) t -> ('a, 'mut) t (** Reverse the vector *) -val rev' : 'a t -> unit +val rev' : ('a, rw) t -> unit (** Reverse the vector in place *) -val size : 'a t -> int +val size : ('a,_) t -> int (** number of elements in vector *) -val length : _ t -> int +val length : (_,_) t -> int (** Synonym for {! size} *) -val capacity : _ t -> int +val capacity : (_,_) t -> int (** Number of elements the vector can contain without being resized *) -val unsafe_get_array : 'a t -> 'a array +val unsafe_get_array : ('a, rw) t -> 'a array (** Access the underlying {b shared} array (do not modify!). [unsafe_get_array v] is longer than [size v], but elements at higher index than [size v] are undefined (do not access!). *) -val (--) : int -> int -> int t +val (--) : int -> int -> (int, 'mut) t (** Range of integers (both included) *) -val of_array : 'a array -> 'a t -val of_list : 'a list -> 'a t -val to_array : 'a t -> 'a array -val to_list : 'a t -> 'a list +val of_array : 'a array -> ('a, 'mut) t +val of_list : 'a list -> ('a, 'mut) t +val to_array : ('a,_) t -> 'a array +val to_list : ('a,_) t -> 'a list -val of_seq : ?init:'a t -> 'a sequence -> 'a t +val of_seq : ?init:('a,rw) t -> 'a sequence -> ('a, rw) t -val to_seq : 'a t -> 'a sequence +val to_seq : ('a,_) t -> 'a sequence -val slice : 'a t -> int -> int -> 'a sequence +val slice : ('a,_) t -> int -> int -> 'a sequence (** [slice v start len] is the sequence of elements from [v.(start)] to [v.(start+len-1)]. *) -val of_klist : ?init:'a t -> 'a klist -> 'a t -val to_klist : 'a t -> 'a klist -val of_gen : ?init:'a t -> 'a gen -> 'a t -val to_gen : 'a t -> 'a gen +val of_klist : ?init:('a, rw) t -> 'a klist -> ('a, rw) t +val to_klist : ('a,_) t -> 'a klist +val of_gen : ?init:('a, rw) t -> 'a gen -> ('a, rw) t +val to_gen : ('a,_) t -> 'a gen val pp : ?start:string -> ?stop:string -> ?sep:string -> - 'a printer -> 'a t printer + 'a printer -> ('a,_) t printer val print : ?start:string -> ?stop:string -> ?sep:string -> - 'a formatter -> 'a t formatter + 'a formatter -> ('a,_) t formatter