diff --git a/doc/api.tex b/doc/api.tex index 4b1a40bc3937f22aaca8c53d66724820b8270b72..5bb4d3b047ac65282acbc76b85b142e3ec540074 100644 --- a/doc/api.tex +++ b/doc/api.tex @@ -19,7 +19,7 @@ the source distribution as \url{examples/use_api.ml}. The first step is to know how to build propositional formulas. The module \texttt{Term} gives a few functions for building these. Here is a piece of OCaml code for building the formula $true \lor false$. -\begin{verbatim} +\begin{ocamlcode} (* opening the Why3 library *) open Why3 @@ -27,7 +27,7 @@ open Why3 let fmla_true : Term.term = Term.t_true let fmla_false : Term.term = Term.t_false let fmla1 : Term.term = Term.t_or fmla_true fmla_false -\end{verbatim} +\end{ocamlcode} The library uses the common type \texttt{term} both for terms (i.e.~expressions that produce a value of some particular type) and formulas (i.e.~boolean-valued expressions). @@ -38,11 +38,11 @@ and formulas (i.e.~boolean-valued expressions). Such a formula can be printed using the module \texttt{Pretty} providing pretty-printers. -\begin{verbatim} +\begin{ocamlcode} (* printing it *) open Format let () = printf "@[formula 1 is:@ %a@]@." Pretty.print_term fmla1 -\end{verbatim} +\end{ocamlcode} Assuming the lines above are written in a file \texttt{f.ml}, it can be compiled using @@ -58,23 +58,23 @@ formula 1 is: true \/ false Let's now build a formula with propositional variables: $A \land B \rightarrow A$. Propositional variables must be declared first before using them in formulas. This is done as follows. -\begin{verbatim} +\begin{ocamlcode} let prop_var_A : Term.lsymbol = Term.create_psymbol (Ident.id_fresh "A") [] let prop_var_B : Term.lsymbol = Term.create_psymbol (Ident.id_fresh "B") [] -\end{verbatim} +\end{ocamlcode} The type \texttt{lsymbol} is the type of function and predicate symbols (which we call logic symbols for brevity). Then the atoms $A$ and $B$ must be built by the general function for applying a predicate symbol to a list of terms. Here we just need the empty list of arguments. -\begin{verbatim} +\begin{ocamlcode} let atom_A : Term.term = Term.ps_app prop_var_A [] let atom_B : Term.term = Term.ps_app prop_var_B [] let fmla2 : Term.term = Term.t_implies (Term.t_and atom_A atom_B) atom_A let () = printf "@[formula 2 is:@ %a@]@." Pretty.print_term fmla2 -\end{verbatim} +\end{ocamlcode} As expected, the output is as follows. \begin{verbatim} @@ -93,13 +93,13 @@ tasks from our formulas. Task can be build incrementally from an empty task by adding declaration to it, using the functions \texttt{add\_*\_decl} of module \texttt{Task}. For the formula $true \lor false$ above, this is done as follows. -\begin{verbatim} +\begin{ocamlcode} let task1 : Task.task = None (* empty task *) let goal_id1 : Decl.prsymbol = Decl.create_prsymbol (Ident.id_fresh "goal1") let task1 : Task.task = Task.add_prop_decl task1 Decl.Pgoal goal_id1 fmla1 -\end{verbatim} +\end{ocamlcode} To make the formula a goal, we must give a name to it, here "goal1". A goal name has type \texttt{prsymbol}, for identifiers denoting propositions in a theory or a task. Notice again that the concrete @@ -112,15 +112,15 @@ and can only be used in theories). Once a task is built, it can be printed. -\begin{verbatim} +\begin{ocamlcode} (* printing the task *) let () = printf "@[task 1 is:@\n%a@]@." Pretty.print_task task1 -\end{verbatim} +\end{ocamlcode} The task for our second formula is a bit more complex to build, because the variables A and B must be added as abstract (i.e.~not defined) propositional symbols in the task. -\begin{verbatim} +\begin{ocamlcode} (* task for formula 2 *) let task2 = None let task2 = Task.add_param_decl task2 prop_var_A @@ -128,7 +128,7 @@ let task2 = Task.add_param_decl task2 prop_var_B let goal_id2 = Decl.create_prsymbol (Ident.id_fresh "goal2") let task2 = Task.add_prop_decl task2 Decl.Pgoal goal_id2 fmla2 let () = printf "@[task 2 is:@\n%a@]@." Pretty.print_task task2 -\end{verbatim} +\end{ocamlcode} Execution of our OCaml program now outputs: \begin{verbatim} @@ -154,7 +154,7 @@ file \texttt{why3.conf}, as it was built using the \texttt{why3config} command line tool or the \textsf{Detect Provers} menu of the graphical IDE. The following API calls allow to access the content of this configuration file. -\begin{verbatim} +\begin{ocamlcode} (* reads the config file *) let config : Whyconf.config = Whyconf.read_config None (* the [main] section of the config file *) @@ -162,24 +162,24 @@ let main : Whyconf.main = Whyconf.get_main config (* all the provers detected, from the config file *) let provers : Whyconf.config_prover Whyconf.Mprover.t = Whyconf.get_provers config -\end{verbatim} +\end{ocamlcode} The type \texttt{'a Whyconf.Mprover.t} is a map indexed by provers. A provers is a record with a name, a version and an alternative description (if someone want to compare different command line options of the same provers for example). It's definition is in the module \texttt{Whyconf} : -\begin{verbatim} +\begin{ocamlcode} type prover = { prover_name : string; (* "Alt-Ergo" *) prover_version : string; (* "2.95" *) prover_altern : string; (* "special" *) } -\end{verbatim} +\end{ocamlcode} The map \texttt{provers} provides the set of existing provers. In the following, we directly attempt to access the prover Alt-Ergo, which is known to be identified with id \texttt{"alt-ergo"}. -\begin{verbatim} +\begin{ocamlcode} (* the [prover alt-ergo] section of the config file *) let alt_ergo : Whyconf.config_prover = try @@ -187,9 +187,9 @@ let alt_ergo : Whyconf.config_prover = with Whyconf.ProverNotFound _ -> eprintf "Prover alt-ergo not installed or not configured@."; exit 0 -\end{verbatim} +\end{ocamlcode} We could also get a specific version with : -\begin{verbatim} +\begin{ocamlcode} let alt_ergo : Whyconf.config_prover = try let prover = {Whyconf.prover_name = "Alt-Ergo"; @@ -199,12 +199,12 @@ let alt_ergo : Whyconf.config_prover = with Not_found -> eprintf "Prover alt-ergo not installed or not configured@."; exit 0 -\end{verbatim} +\end{ocamlcode} The next step is to obtain the driver associated to this prover. A driver typically depends on the standard theories so these should be loaded first. -\begin{verbatim} +\begin{ocamlcode} (* builds the environment from the [loadpath] *) let env : Env.env = Env.create_env (Whyconf.loadpath main) @@ -216,12 +216,12 @@ let alt_ergo_driver : Driver.driver = eprintf "Failed to load driver for alt-ergo: %a@." Exn_printer.exn_printer e; exit 1 -\end{verbatim} +\end{ocamlcode} We are now ready to call the prover on the tasks. This is done by a function call that launches the external executable and waits for its termination. Here is a simple way to proceed: -\begin{verbatim} +\begin{ocamlcode} (* calls Alt-Ergo *) let result1 : Call_provers.prover_result = Call_provers.wait_on_call @@ -230,7 +230,7 @@ let result1 : Call_provers.prover_result = (* prints Alt-Ergo answer *) let () = printf "@[On task 1, alt-ergo answers %a@]@." Call_provers.print_prover_result result1 -\end{verbatim} +\end{ocamlcode} This way to call a prover is in general too naive, since it may never return if the prover runs without time limit. The function \texttt{prove\_task} has two optional parameters: \texttt{timelimit} @@ -261,7 +261,7 @@ A \texttt{pr\_answer} is a sum of several kind of answers: \end{itemize} Here is thus another way of calling the Alt-Ergo prover, on our second task. -\begin{verbatim} +\begin{ocamlcode} let result2 : Call_provers.prover_result = Call_provers.wait_on_call (Driver.prove_task ~command:alt_ergo.Whyconf.command @@ -273,7 +273,7 @@ let () = Call_provers.print_prover_answer result1.Call_provers.pr_answer result1.Call_provers.pr_time -\end{verbatim} +\end{ocamlcode} The output of our program is now as follows. \begin{verbatim} On task 1, alt-ergo answers Valid (0.01s) @@ -290,7 +290,7 @@ Here is the way we build the formula $2+2=4$. The main difficulty is to access the internal identifier for addition: it must be retrieved from the standard theory \texttt{Int} of the file \texttt{int.why} (see Chap~\ref{chap:library}). -\begin{verbatim} +\begin{ocamlcode} let two : Term.term = Term.t_const (Term.ConstInt (Term.IConstDecimal "2")) let four : Term.term = Term.t_const (Term.ConstInt (Term.IConstDecimal "4")) let int_theory : Theory.theory = @@ -300,52 +300,52 @@ let plus_symbol : Term.lsymbol = let two_plus_two : Term.term = Term.t_app_infer plus_symbol [two;two] let fmla3 : Term.term = Term.t_equ two_plus_two four -\end{verbatim} +\end{ocamlcode} An important point to notice as that when building the application of $+$ to the arguments, it is checked that the types are correct. Indeed the constructor \texttt{t\_app\_infer} infers the type of the resulting term. One could also provide the expected type as follows. -\begin{verbatim} +\begin{ocamlcode} let two_plus_two : Term.term = Term.fs_app plus_symbol [two;two] Ty.ty_int -\end{verbatim} +\end{ocamlcode} When building a task with this formula, we need to declare that we use theory \texttt{Int}: -\begin{verbatim} +\begin{ocamlcode} let task3 = None let task3 = Task.use_export task3 int_theory let goal_id3 = Decl.create_prsymbol (Ident.id_fresh "goal3") let task3 = Task.add_prop_decl task3 Decl.Pgoal goal_id3 fmla3 -\end{verbatim} +\end{ocamlcode} \section{Building Quantified Formulas} To illustrate how to build quantified formulas, let us consider the formula $\forall x:int. x*x \geq 0$. The first step is to obtain the symbols from \texttt{Int}. -\begin{verbatim} +\begin{ocamlcode} let zero : Term.term = Term.t_const (Term.ConstInt "0") let mult_symbol : Term.lsymbol = Theory.ns_find_ls int_theory.Theory.th_export ["infix *"] let ge_symbol : Term.lsymbol = Theory.ns_find_ls int_theory.Theory.th_export ["infix >="] -\end{verbatim} +\end{ocamlcode} The next step is to introduce the variable $x$ with the type int. -\begin{verbatim} +\begin{ocamlcode} let var_x : Term.vsymbol = Term.create_vsymbol (Ident.id_fresh "x") Ty.ty_int -\end{verbatim} +\end{ocamlcode} The formula $x*x \geq 0$ is obtained as in the previous example. -\begin{verbatim} +\begin{ocamlcode} let x : Term.term = Term.t_var var_x let x_times_x : Term.term = Term.t_app_infer mult_symbol [x;x] let fmla4_aux : Term.term = Term.ps_app ge_symbol [x_times_x;zero] -\end{verbatim} +\end{ocamlcode} To quantify on $x$, we use the appropriate smart constructor as follows. -\begin{verbatim} +\begin{ocamlcode} let fmla4 : Term.term = Term.t_forall_close [var_x] [] fmla4_aux -\end{verbatim} +\end{ocamlcode} \section{Building Theories} diff --git a/doc/macros.tex b/doc/macros.tex index cd4fca67d8fa35804eb1b25a9792c5d155b541f6..34b3802cf14632ee02c88039ecae545d7e6d33b3 100644 --- a/doc/macros.tex +++ b/doc/macros.tex @@ -39,7 +39,16 @@ \RequirePackage{listings} \RequirePackage{amssymb} -\lstset{basicstyle={\ttfamily},framesep=2pt,frame=single} +\lstset{ + basicstyle={\ttfamily}, + framesep=2pt, + frame=single, + keywordstyle={\color{blue}}, + stringstyle=\itshape, + commentstyle=\itshape, + columns=[l]fullflexible, + showstringspaces=false, +} \lstdefinelanguage{why3} { @@ -48,13 +57,7 @@ import,export,theory,module,end,in,with,% let,rec,for,to,do,done,match,if,then,else,while,try,invariant,variant,% absurd,raise,assert,exception,% goal,axiom,lemma,forall},% -keywordstyle={\color{blue}},% -otherkeywords={},% string=[b]",% -showstringspaces=false,% -stringstyle=\itshape,% -commentstyle=\itshape,% -columns=[l]fullflexible,% sensitive=true,% morecomment=[s]{(*}{*)},% keepspaces=true, @@ -82,6 +85,7 @@ literate=% } \lstnewenvironment{whycode}{\lstset{language=why3}}{} +\lstnewenvironment{ocamlcode}{\lstset{language={[Objective]Caml}}}{} %%% Local Variables: %%% mode: latex