diff --git a/stdlib/stack.ml b/stdlib/stack.ml index 4db3d5b43..e65be5f35 100644 --- a/stdlib/stack.ml +++ b/stdlib/stack.ml @@ -11,30 +11,30 @@ (* *) (***********************************************************************) -type 'a t = { mutable c : 'a list } +type 'a t = { mutable c : 'a list; mutable len : int; } exception Empty -let create () = { c = [] } +let create () = { c = []; len = 0; } -let clear s = s.c <- [] +let clear s = s.c <- []; s.len <- 0 -let copy s = { c = s.c } +let copy s = { c = s.c; len = s.len; } -let push x s = s.c <- x :: s.c +let push x s = s.c <- x :: s.c; s.len <- s.len + 1 let pop s = match s.c with - hd::tl -> s.c <- tl; hd + | hd::tl -> s.c <- tl; s.len <- s.len - 1; hd | [] -> raise Empty let top s = match s.c with - hd::_ -> hd + | hd::_ -> hd | [] -> raise Empty let is_empty s = (s.c = []) -let length s = List.length s.c +let length s = s.len let iter f s = List.iter f s.c diff --git a/stdlib/stack.mli b/stdlib/stack.mli index 9b468aa6c..5874e648e 100644 --- a/stdlib/stack.mli +++ b/stdlib/stack.mli @@ -47,7 +47,7 @@ val is_empty : 'a t -> bool (** Return [true] if the given stack is empty, [false] otherwise. *) val length : 'a t -> int -(** Return the number of elements in a stack. *) +(** Return the number of elements in a stack. Time complexity O(1) *) val iter : ('a -> unit) -> 'a t -> unit (** [iter f s] applies [f] in turn to all elements of [s], diff --git a/testsuite/tests/lib-stack/Makefile b/testsuite/tests/lib-stack/Makefile new file mode 100644 index 000000000..299656b24 --- /dev/null +++ b/testsuite/tests/lib-stack/Makefile @@ -0,0 +1,15 @@ +######################################################################### +# # +# OCaml # +# # +# Xavier Clerc, SED, INRIA Rocquencourt # +# # +# Copyright 2010 Institut National de Recherche en Informatique et # +# en Automatique. All rights reserved. This file is distributed # +# under the terms of the Q Public License version 1.0. # +# # +######################################################################### + +BASEDIR=../.. +include $(BASEDIR)/makefiles/Makefile.several +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/lib-stack/test.ml b/testsuite/tests/lib-stack/test.ml new file mode 100644 index 000000000..e8df9a264 --- /dev/null +++ b/testsuite/tests/lib-stack/test.ml @@ -0,0 +1,127 @@ +(***********************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jeremie Dimino, Jane Street Europe *) +(* *) +(* Copyright 2015 Institut National de Recherche en Informatique et *) +(* en Automatique. All rights reserved. This file is distributed *) +(* under the terms of the S Public License version 1.0. *) +(* *) +(***********************************************************************) + +module S = struct + include Stack + + let to_list s = let l = ref [] in iter (fun x -> l := x :: !l) s; !l (* from bottom to top *) +end + +let does_raise f s = + try + ignore (f s : int); + false + with S.Empty -> + true + +let () = + let s = S.create () in + (); assert (S.to_list s = [ ] && S.length s = 0); + S.push 1 s; assert (S.to_list s = [1 ] && S.length s = 1); + S.push 2 s; assert (S.to_list s = [1; 2 ] && S.length s = 2); + S.push 3 s; assert (S.to_list s = [1; 2; 3 ] && S.length s = 3); + S.push 4 s; assert (S.to_list s = [1; 2; 3; 4] && S.length s = 4); + assert (S.pop s = 4); assert (S.to_list s = [1; 2; 3; ] && S.length s = 3); + assert (S.pop s = 3); assert (S.to_list s = [1; 2; ] && S.length s = 2); + assert (S.pop s = 2); assert (S.to_list s = [1; ] && S.length s = 1); + assert (S.pop s = 1); assert (S.to_list s = [ ] && S.length s = 0); + assert (does_raise S.pop s); +;; + +let () = + let s = S.create () in + S.push 1 s; assert (S.pop s = 1); assert (does_raise S.pop s); + S.push 2 s; assert (S.pop s = 2); assert (does_raise S.pop s); + assert (S.length s = 0); +;; + +let () = + let s = S.create () in + S.push 1 s; assert (S.top s = 1); + S.push 2 s; assert (S.top s = 2); + S.push 3 s; assert (S.top s = 3); + assert (S.top s = 3); assert (S.pop s = 3); + assert (S.top s = 2); assert (S.pop s = 2); + assert (S.top s = 1); assert (S.pop s = 1); + assert (does_raise S.top s); + assert (does_raise S.top s); +;; + +let () = + let s = S.create () in + for i = 1 to 10 do S.push i s done; + S.clear s; + assert (S.length s = 0); + assert (does_raise S.pop s); + assert (s = S.create ()); + S.push 42 s; + assert (S.pop s = 42); +;; + +let () = + let s1 = S.create () in + for i = 1 to 10 do S.push i s1 done; + let s2 = S.copy s1 in + assert (S.to_list s1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]); + assert (S.to_list s2 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]); + assert (S.length s1 = 10); + assert (S.length s2 = 10); + for i = 10 downto 1 do + assert (S.pop s1 = i); + done; + for i = 10 downto 1 do + assert (S.pop s2 = i); + done; +;; + +let () = + let s = S.create () in + assert (S.is_empty s); + for i = 1 to 10 do + S.push i s; + assert (S.length s = i); + assert (not (S.is_empty s)); + done; + for i = 10 downto 1 do + assert (S.length s = i); + assert (not (S.is_empty s)); + ignore (S.pop s : int); + done; + assert (S.length s = 0); + assert (S.is_empty s); +;; + +let () = + let s = S.create () in + for i = 10 downto 1 do S.push i s done; + let i = ref 1 in + S.iter (fun j -> assert (!i = j); incr i) s; +;; + +let () = + let s1 = S.create () in + assert (S.length s1 = 0); assert (S.to_list s1 = []); + let s2 = S.copy s1 in + assert (S.length s1 = 0); assert (S.to_list s1 = []); + assert (S.length s2 = 0); assert (S.to_list s2 = []); +;; + +let () = + let s1 = S.create () and s2 = S.create () in + for i = 1 to 4 do S.push i s1 done; + assert (S.length s1 = 4); assert (S.to_list s1 = [1; 2; 3; 4]); + let s2 = S.copy s1 in + assert (S.length s1 = 4); assert (S.to_list s1 = [1; 2; 3; 4]); + assert (S.length s2 = 4); assert (S.to_list s2 = [1; 2; 3; 4]); +;; + +let () = print_endline "OK" diff --git a/testsuite/tests/lib-stack/test.reference b/testsuite/tests/lib-stack/test.reference new file mode 100644 index 000000000..d86bac9de --- /dev/null +++ b/testsuite/tests/lib-stack/test.reference @@ -0,0 +1 @@ +OK