Commit f840e0be authored by MARCHE Claude's avatar MARCHE Claude

Why3doc for modules

parent 412b6e68
...@@ -1000,11 +1000,11 @@ $(WHY3DOCDEP): $(WHY3DOCGENERATED) ...@@ -1000,11 +1000,11 @@ $(WHY3DOCDEP): $(WHY3DOCGENERATED)
byte: bin/why3doc.byte byte: bin/why3doc.byte
opt: bin/why3doc.opt opt: bin/why3doc.opt
bin/why3doc.opt: src/why3.cmxa $(WHY3DOCCMX) bin/why3doc.opt: src/why3.cmxa $(PGMCMX) $(WHY3DOCCMX)
$(if $(QUIET),@echo 'Linking $@' &&) \ $(if $(QUIET),@echo 'Linking $@' &&) \
$(OCAMLOPT) $(OFLAGS) -o $@ $(OLINKFLAGS) $^ $(OCAMLOPT) $(OFLAGS) -o $@ $(OLINKFLAGS) $^
bin/why3doc.byte: src/why3.cma $(WHY3DOCCMO) bin/why3doc.byte: src/why3.cma $(PGMCMO) $(WHY3DOCCMO)
$(if $(QUIET),@echo 'Linking $@' &&) \ $(if $(QUIET),@echo 'Linking $@' &&) \
$(OCAMLC) $(BFLAGS) -o $@ $(BLINKFLAGS) $^ $(OCAMLC) $(BFLAGS) -o $@ $(BLINKFLAGS) $^
...@@ -1189,12 +1189,16 @@ STDLIBS = bool comparison relations \ ...@@ -1189,12 +1189,16 @@ STDLIBS = bool comparison relations \
option list map set bag graph option list map set bag graph
# function ? sum ? tptp ? # function ? sum ? tptp ?
STDMODS = ref array arith hashtbl impset pqueue queue random stack string
STDLIBFILES = $(addsuffix .why, $(addprefix theories/, $(STDLIBS))) STDLIBFILES = $(addsuffix .why, $(addprefix theories/, $(STDLIBS)))
STDMODFILES = $(addsuffix .mlw, $(addprefix modules/, $(STDMODS)))
stdlibdoc: $(STDLIBFILES) bin/why3doc stdlibdoc: $(STDLIBFILES) $(STDMODFILES) bin/why3doc
mkdir -p doc/stdlibdoc mkdir -p doc/stdlibdoc
rm -f doc/stdlibdoc/style.css rm -f doc/stdlibdoc/style.css
WHY3LOADPATH=theories bin/why3doc -o doc/stdlibdoc $(STDLIBFILES) WHY3LOADPATH=theories bin/why3doc -L modules -o doc/stdlibdoc \
$(STDLIBFILES) $(STDMODFILES)
clean:: clean::
rm -f doc/stdlibdoc/* rm -f doc/stdlibdoc/*
......
(* Arithmetic for programs *) (** {1 Arithmetic for programs} *)
(** {2 Integer Division}
It is checked that divisor is not null
*)
module Int module Int
...@@ -8,9 +14,14 @@ module Int ...@@ -8,9 +14,14 @@ module Int
let (/) (x: int) (y:int) = { y <> 0 } div x y { result = div x y } let (/) (x: int) (y:int) = { y <> 0 } div x y { result = div x y }
end end
(* machine arithmetic (32-bit integers, etc.) will go here *) (** {2 Machine integers}
32-bit integers and such go here
*)
module Int32 module Int32
use export int.Int use export int.Int
...@@ -36,6 +47,11 @@ module Int32 ...@@ -36,6 +47,11 @@ module Int32
end end
(** {2 Division on real numbers}
See also Floating-Point theories
*)
module Real module Real
use import real.Real use import real.Real
...@@ -46,7 +62,7 @@ module Real ...@@ -46,7 +62,7 @@ module Real
end end
(* (***
Local Variables: Local Variables:
compile-command: "unset LANG; make -C .. modules/arith" compile-command: "unset LANG; make -C .. modules/arith"
End: End:
......
(** {1 Arrays} *)
(* Arrays *) (** {2 Generic Arrays}
The length is a non-mutable field, so that we get for free that modification of an array does not modify its length
*)
module Array module Array
...@@ -13,7 +18,7 @@ module Array ...@@ -13,7 +18,7 @@ module Array
function set (a: array 'a) (i: int) (v: 'a) : array 'a = function set (a: array 'a) (i: int) (v: 'a) : array 'a =
{| a with elts = M.set a.elts i v |} {| a with elts = M.set a.elts i v |}
(* syntactic sugar *) (** syntactic sugar *)
function ([]) (a: array 'a) (i: int) : 'a = get a i function ([]) (a: array 'a) (i: int) : 'a = get a i
function ([<-]) (a: array 'a) (i: int) (v: 'a) : array 'a = set a i v function ([<-]) (a: array 'a) (i: int) (v: 'a) : array 'a = set a i v
...@@ -25,7 +30,7 @@ module Array ...@@ -25,7 +30,7 @@ module Array
val length (a: array 'a) : {} int { result = a.length } val length (a: array 'a) : {} int { result = a.length }
(* unsafe get/set operations with no precondition *) (** unsafe get/set operations with no precondition *)
exception OutOfBounds exception OutOfBounds
let defensive_get (a: array 'a) (i: int) = let defensive_get (a: array 'a) (i: int) =
...@@ -46,7 +51,7 @@ module Array ...@@ -46,7 +51,7 @@ module Array
{ n >= 0 } { n >= 0 }
array 'a array 'a
{ result = {| length = n; elts = M.const v |} } { result = {| length = n; elts = M.const v |} }
(* { length result = n /\ forall i:int. 0 <= i < n -> result[i] = v} *) (*** { length result = n /\ forall i:int. 0 <= i < n -> result[i] = v} *)
val append (a1: array 'a) (a2: array 'a) : val append (a1: array 'a) (a2: array 'a) :
{} {}
...@@ -97,7 +102,7 @@ module Array ...@@ -97,7 +102,7 @@ module Array
(forall i:int. (forall i:int.
ofs2 <= i < ofs2 + len -> a2[i] = a1[ofs1 + i - ofs2]) } ofs2 <= i < ofs2 + len -> a2[i] = a1[ofs1 + i - ofs2]) }
(* TODO? (*** TODO?
- concat : 'a array list -> 'a array - concat : 'a array list -> 'a array
- to_list - to_list
- of_list - of_list
...@@ -105,6 +110,9 @@ module Array ...@@ -105,6 +110,9 @@ module Array
end end
(** {2 Sorted Arrays} *)
module ArraySorted module ArraySorted
use import int.Int use import int.Int
...@@ -119,6 +127,8 @@ module ArraySorted ...@@ -119,6 +127,8 @@ module ArraySorted
end end
(** {2 Arrays Equality} *)
module ArrayEq module ArrayEq
use import module Array use import module Array
...@@ -133,6 +143,8 @@ module ArrayEq ...@@ -133,6 +143,8 @@ module ArrayEq
end end
(** {2 Permutation} *)
module ArrayPermut module ArrayPermut
use import int.Int use import int.Int
...@@ -174,12 +186,14 @@ module ArrayPermut ...@@ -174,12 +186,14 @@ module ArrayPermut
end end
(** {2 Sum of elements} *)
module ArraySum module ArraySum
use import module Array use import module Array
clone import map.MapSum as M clone import map.MapSum as M
(* [sum a l h] is the sum of a[i] for l <= i < h *) (** [sum a l h] is the sum of [a[i]] for [l <= i < h] *)
function sum (a: array int) (l h: int) : int = M.sum a.elts l h function sum (a: array int) (l h: int) : int = M.sum a.elts l h
...@@ -222,7 +236,7 @@ module TestArray ...@@ -222,7 +236,7 @@ module TestArray
end end
(* (***
Local Variables: Local Variables:
compile-command: "unset LANG; make -C .. modules/array" compile-command: "unset LANG; make -C .. modules/array"
End: End:
......
(* Hash tables à la OCaml: each key is mapped to a *stack* of values, (** {1 Hash tables}
This module provides Hash tables à la OCaml. Each key is mapped to a *stack* of values,
with [add h k v] pushing a new value [v] for key [k], with [add h k v] pushing a new value [v] for key [k],
and [remove h k] popping a value for key [key]. *) and [remove h k] popping a value for key [key].
*)
module Hashtbl module Hashtbl
...@@ -67,7 +71,7 @@ module Hashtbl ...@@ -67,7 +71,7 @@ module Hashtbl
/\ /\
forall k': key. k' <> k -> h[k'] = (old h)[k'] } forall k': key. k' <> k -> h[k'] = (old h)[k'] }
(* TODO (*** TODO
- val length: t 'a -> int (the number of distinct key) - val length: t 'a -> int (the number of distinct key)
- val iter : ('a -> 'b -> unit) -> ('a, 'b) t -> unit - val iter : ('a -> 'b -> unit) -> ('a, 'b) t -> unit
- val fold : ('a -> 'b -> 'c -> 'c) -> ('a, 'b) t -> 'c -> 'c - val fold : ('a -> 'b -> 'c -> 'c) -> ('a, 'b) t -> 'c -> 'c
...@@ -101,7 +105,7 @@ module TestHashtbl ...@@ -101,7 +105,7 @@ module TestHashtbl
end end
(* (***
Local Variables: Local Variables:
compile-command: "unset LANG; make -C .. modules/hashtbl" compile-command: "unset LANG; make -C .. modules/hashtbl"
End: End:
......
(* An imperative set is simply a reference containing a finite set *) (** {1 Imperative sets}
An imperative set is simply a reference containing a finite set
*)
module Impset module Impset
use export set.Fset use export set.Fset
...@@ -36,7 +41,7 @@ module Impset ...@@ -36,7 +41,7 @@ module Impset
end end
(* (***
Local Variables: Local Variables:
compile-command: "unset LANG; make -C .. modules/impset" compile-command: "unset LANG; make -C .. modules/impset"
End: End:
......
(* Polymorphic mutable priority queues. *) (** {1 Priority queues} *)
(** {2 Polymorphic mutable priority queues} *)
module Pqueue module Pqueue
(** {3 Types} *)
type elt type elt
(* [elt] is equipped with a total order [rel] *) (** [elt] is equipped with a total order [rel] *)
clone export relations.TotalOrder with type t = elt clone export relations.TotalOrder with type t = elt
(* the priority queue is modeled as a list of elements *) (** the priority queue is modeled as a list of elements *)
use import list.List use import list.List
use import list.Mem use import list.Mem
use import list.Permut use import list.Permut
...@@ -16,26 +20,26 @@ module Pqueue ...@@ -16,26 +20,26 @@ module Pqueue
type t model {| mutable elts: list elt |} type t model {| mutable elts: list elt |}
(* Operations. *) (** {3 Operations} *)
(* creates a fresh, empty queue *) (** creates a fresh, empty queue *)
val create: unit -> {} t { result.elts = Nil } val create: unit -> {} t { result.elts = Nil }
(* pushes an element in a queue *) (** pushes an element in a queue *)
val push: val push:
x: elt -> q: t -> x: elt -> q: t ->
{ } { }
unit writes q unit writes q
{ q.elts = Cons x (old q.elts) } { q.elts = Cons x (old q.elts) }
(* exception raised by pop and peek to signal an empty queue *) (** exception raised by [pop] and [peek] to signal an empty queue *)
exception Empty exception Empty
(* pop and peek return the minimal element, defined as follows *) (** [pop] and [peek] return the minimal element, defined as follows *)
predicate minimal_elt (x: elt) (s: list elt) = predicate minimal_elt (x: elt) (s: list elt) =
mem x s /\ forall e: elt. mem e s -> rel x e mem x s /\ forall e: elt. mem e s -> rel x e
(* removes and returns the minimal element *) (** removes and returns the minimal element *)
val pop: val pop:
q: t -> q: t ->
{} {}
...@@ -45,7 +49,7 @@ module Pqueue ...@@ -45,7 +49,7 @@ module Pqueue
minimal_elt result (old q.elts) } minimal_elt result (old q.elts) }
| Empty -> { q.elts = (old q.elts) = Nil } | Empty -> { q.elts = (old q.elts) = Nil }
(* returns the minimal element, without modifying the queue *) (** returns the minimal element, without modifying the queue *)
val peek: val peek:
q: t -> q: t ->
{} {}
...@@ -53,17 +57,17 @@ module Pqueue ...@@ -53,17 +57,17 @@ module Pqueue
reads q raises Empty reads q raises Empty
{ minimal_elt result q.elts } | Empty -> { q.elts = Nil } { minimal_elt result q.elts } | Empty -> { q.elts = Nil }
(* empties the queue *) (** empties the queue *)
val clear: q: t -> {} unit writes q {q.elts = Nil } val clear: q: t -> {} unit writes q {q.elts = Nil }
(* returns a fresh copy of the queue *) (** returns a fresh copy of the queue *)
val copy: q: t -> {} t reads q { result = q } val copy: q: t -> {} t reads q { result = q }
(* checks whether the queue is empty *) (** checks whether the queue is empty *)
val is_empty: val is_empty:
q: t -> {} bool reads q { result=True <-> q.elts = Nil } q: t -> {} bool reads q { result=True <-> q.elts = Nil }
(* returns the number of elements in the queue *) (** returns the number of elements in the queue *)
val length: q: t -> {} int reads q { result = length q.elts } val length: q: t -> {} int reads q { result = length q.elts }
end end
...@@ -95,43 +99,47 @@ module Test ...@@ -95,43 +99,47 @@ module Test
end end
(* Simpler interface when duplicate elements are not allowed *) (** {2 Simpler interface}
when duplicate elements are not allowed
*)
module PqueueNoDup module PqueueNoDup
(* Types. *) (** {3 Types} *)
(* the abstract type of elements *) (** the abstract type of elements *)
type elt type elt
(* [elt] is equipped with a total order [rel] *) (** [elt] is equipped with a total order [rel] *)
clone export relations.TotalOrder with type t = elt clone export relations.TotalOrder with type t = elt
(* the priority queue is modeled as a finite set of elements *) (** the priority queue is modeled as a finite set of elements *)
use import set.Fset use import set.Fset
type t model {| mutable elts: set elt |} type t model {| mutable elts: set elt |}
(* Operations. *) (** {3 Operations} *)
(* creates a fresh, empty queue *) (** creates a fresh, empty queue *)
val create: unit -> {} t { result.elts = empty } val create: unit -> {} t { result.elts = empty }
(* pushes an element in a queue *) (** pushes an element in a queue *)
val push: val push:
x: elt -> q: t -> x: elt -> q: t ->
{ } { }
unit writes q unit writes q
{ q.elts = add x (old q.elts) } { q.elts = add x (old q.elts) }
(* exception raised by pop and peek to signal an empty queue *) (** exception raised by [pop] and [peek] to signal an empty queue *)
exception Empty exception Empty
(* pop and peek return the minimal element, defined as follows *) (** [pop] and [peek] return the minimal element, defined as follows *)
predicate minimal_elt (x: elt) (s: set elt) = predicate minimal_elt (x: elt) (s: set elt) =
mem x s /\ forall e: elt. mem e s -> rel x e mem x s /\ forall e: elt. mem e s -> rel x e
(* removes and returns the minimal element *) (** removes and returns the minimal element *)
val pop: val pop:
q: t -> q: t ->
{} {}
...@@ -140,7 +148,7 @@ module PqueueNoDup ...@@ -140,7 +148,7 @@ module PqueueNoDup
{ q.elts = remove result (old q.elts) /\ minimal_elt result (old q.elts) } { q.elts = remove result (old q.elts) /\ minimal_elt result (old q.elts) }
| Empty -> { q.elts = (old q.elts) = empty } | Empty -> { q.elts = (old q.elts) = empty }
(* returns the minimal element, without modifying the queue *) (** returns the minimal element, without modifying the queue *)
val peek: val peek:
q: t -> q: t ->
{} {}
...@@ -148,17 +156,17 @@ module PqueueNoDup ...@@ -148,17 +156,17 @@ module PqueueNoDup
reads q raises Empty reads q raises Empty
{ minimal_elt result q.elts } | Empty -> { q.elts = empty } { minimal_elt result q.elts } | Empty -> { q.elts = empty }
(* empties the queue *) (** empties the queue *)
val clear: q: t -> {} unit writes q {q.elts = empty } val clear: q: t -> {} unit writes q {q.elts = empty }
(* returns a fresh copy of the queue *) (** returns a fresh copy of the queue *)
val copy: q: t -> {} t reads q { result = q } val copy: q: t -> {} t reads q { result = q }
(* checks whether the queue is empty *) (** checks whether the queue is empty *)
val is_empty: val is_empty:
q: t -> {} bool reads q { result=True <-> q.elts = empty } q: t -> {} bool reads q { result=True <-> q.elts = empty }
(* returns the number of elements in the queue *) (** returns the number of elements in the queue *)
val length: q: t -> {} int reads q { result = cardinal q.elts } val length: q: t -> {} int reads q { result = cardinal q.elts }
end end
...@@ -190,7 +198,7 @@ module TestNoDup ...@@ -190,7 +198,7 @@ module TestNoDup
end end
(* (***
Local Variables: Local Variables:
compile-command: "unset LANG; make -C .. modules/pqueue" compile-command: "unset LANG; make -C .. modules/pqueue"
End: End:
......
(* Polymorphic mutable queues *) (** {1 Polymorphic mutable queues} *)
module Queue module Queue
...@@ -68,7 +68,7 @@ module Test ...@@ -68,7 +68,7 @@ module Test
end end
(* (***
Local Variables: Local Variables:
compile-command: "unset LANG; make -C .. modules/queue" compile-command: "unset LANG; make -C .. modules/queue"
End: End:
......
(* Pseudo-random generators. (** {1 Pseudo-random generators}
This easiest way to get random numbers (of random values of any type) This easiest way to get random numbers (of random values of any type)
is to take advantage of the non-determinism of Hoare triples. is to take advantage of the non-determinism of Hoare triples.
Simply declaring a function Simply declaring a function
val random_int: unit -> {} int {} [val random_int: unit -> {} int {}]
is typically enough. Two calls to random_int return values that can not is typically enough. Two calls to [random_int] return values that can not
be proved equal, which is exactly what we need. be proved equal, which is exactly what we need.
The following modules provide slightly more: pseudo-random generators The following modules provide slightly more: pseudo-random generators
which are deterministic according to a state. The state is either which are deterministic according to a state. The state is either
explicit (module State) or global (module Random). Functions init allow explicit (module [State]) or global (module [Random]). Functions init allow
to reset the generators according to a given seed. to reset the generators according to a given seed.
*) *)
(* Purely applicative generators. *) (** {2 Purely applicative generators} *)
theory Generator theory Generator
...@@ -39,8 +40,9 @@ theory Generator ...@@ -39,8 +40,9 @@ theory Generator
end end
(* Mutable states of pseudo-random generators. (** {2 Mutable states of pseudo-random generators}
Basically a reference containing a pure generator. *)
Basically a reference containing a pure generator. *)
module State module State
...@@ -71,7 +73,7 @@ module State ...@@ -71,7 +73,7 @@ module State
end end
(* A global pseudo-random generator. *) (** {2 A global pseudo-random generator} *)
module Random module Random
...@@ -112,7 +114,7 @@ module Test ...@@ -112,7 +114,7 @@ module Test
end end
(* (***
Local Variables: Local Variables:
compile-command: "unset LANG; make -C .. modules/random" compile-command: "unset LANG; make -C .. modules/random"
End: End:
......
(* References. (** {1 References}
A mutable variable, or ``reference'' in ML terminology, is simply a A mutable variable, or ``reference'' in ML terminology, is simply a
record with a single mutable field 'contents'. record with a single mutable field [contents].
Creation, access, and assignment are provided as 'ref', prefix '!', and *)
infix ':=', respectively.
(** {2 Generic references}
Creation, access, and assignment are provided as [ref], prefix [!], and
infix [:=], respectively.
*) *)
module Ref module Ref
...@@ -22,7 +26,9 @@ module Ref ...@@ -22,7 +26,9 @@ module Ref
end end
(* Module Refint adds a few operations specific to integer references. *) (** {2 Integer References}
a few operations specific to integer references *)
module Refint module Refint
...@@ -38,7 +44,7 @@ module Refint ...@@ -38,7 +44,7 @@ module Refint
end end
(* (***
Local Variables: Local Variables:
compile-command: "unset LANG; make -C .. modules/ref" compile-command: "unset LANG; make -C .. modules/ref"
End: End:
......
(* Polymorphic mutable stacks *) (** {1 Stacks} *)
(** {2 Polymorphic mutable stacks} *)
module Stack module Stack
...@@ -39,7 +41,7 @@ module Stack ...@@ -39,7 +41,7 @@ module Stack
val is_empty: val is_empty:
s: t 'a -> {} bool reads s { result=True <-> s.elts = Nil } s: t 'a -> {} bool reads s { result=True <-> s.elts = Nil }
(* (***
val length: s: t 'a -> {} int reads s { result = length s.elts } val length: s: t 'a -> {} int reads s { result = length s.elts }
*) *)
function length (s: t 'a) : int = L.length s.elts function length (s: t 'a) : int = L.length s.elts
...@@ -70,7 +72,7 @@ module Test ...@@ -70,7 +72,7 @@ module Test
end end
(* (***
Local Variables: Local Variables:
compile-command: "unset LANG; make -C .. modules/stack" compile-command: "unset LANG; make -C .. modules/stack"