Commit 6b662f87 authored by Guillaume Melquiond's avatar Guillaume Melquiond

Add syntactic coloring for OCaml code too.

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