Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
why3
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
119
Issues
119
List
Boards
Labels
Service Desk
Milestones
Merge Requests
16
Merge Requests
16
Operations
Operations
Incidents
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Why3
why3
Commits
8b67eba7
Commit
8b67eba7
authored
Apr 09, 2018
by
MARCHE Claude
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
doc/API tuto: auto extracted code, completed
parent
fca13b5b
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
77 additions
and
196 deletions
+77
-196
Makefile.in
Makefile.in
+5
-1
doc/api.tex
doc/api.tex
+19
-177
examples/use_api/logic.ml
examples/use_api/logic.ml
+53
-18
No files found.
Makefile.in
View file @
8b67eba7
...
...
@@ -1837,7 +1837,11 @@ doc/call_provers_%.ml: src/driver/call_provers.ml doc/extract_ocaml_code
OCAMLCODE_LOGIC
=
opening printformula declarepropvars declarepropatoms
\
buildtask printtask buildtask2
\
getconf getanyaltergo getaltergo200
\
getdriver callprover calltimelimit
getdriver callprover calltimelimit
\
buildfmla buildtermalt buildtaskimport
\
quantfmla1 quantfmla2 quantfmla3 quantfmla4
\
buildth1 buildth2 buildth3 buildth4 buildth5 buildth6 buildth7
\
printtheory splittheory printalltasks
OCAMLCODE_CALLPROVERS
=
proveranswer proverresult resourcelimit
...
...
doc/api.tex
View file @
8b67eba7
...
...
@@ -117,86 +117,27 @@ 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{ocamlcode}
% (* reads the config file *)
% let config : Whyconf.config = Whyconf.read_config None
% (* the [main] section of the config file *)
% 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{ocamlcode}
\lstinputlisting
{
logic
_
getconf.ml
}
The type
\texttt
{
'a Whyconf.Mprover.t
}
is a map indexed by provers. A
prover is a record with a name, a version, and an alternative description
(to differentiate between various configurations of a given prover). Its
definition is in the module
\texttt
{
Whyconf
}
:
% \begin{ocamlcode}
% type prover =
% { prover_name : string; (* "Alt-Ergo" *)
% prover_version : string; (* "2.95" *)
% prover_altern : string; (* "special" *)
% }
% \end{ocamlcode}
\lstinputlisting
{
whyconf
_
provertype.ml
}
The map
\texttt
{
provers
}
provides the set of existing provers.
In the following, we directly
attempt to access a prover named ``Alt-Ergo'', any version.
% \begin{ocamlcode}
% (* the [prover alt-ergo] section of the config file *)
% let alt_ergo : Whyconf.config_prover =
% try
% Whyconf.prover_by_id config "alt-ergo"
% with Whyconf.ProverNotFound _ ->
% eprintf "Prover alt-ergo not installed or not configured@.";
% exit 0
% \end{ocamlcode}
\lstinputlisting
{
logic
_
getanyaltergo.ml
}
We could also get a specific version with :
% \begin{ocamlcode}
% let alt_ergo : Whyconf.config_prover =
% try
% let prover = {Whyconf.prover_name = "Alt-Ergo";
% prover_version = "2.0.0";
% prover_altern = ""} in
% Whyconf.Mprover.find prover provers
% with Not_found ->
% eprintf "Prover Alt-Ergo 2.0.0 not installed or not configured@.";
% exit 0
% \end{ocamlcode}
\lstinputlisting
{
logic
_
getaltergo200.ml
}
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{ocamlcode}
% (* builds the environment from the [loadpath] *)
% let env : Env.env =
% Env.create_env (Whyconf.loadpath main)
% (* loading the Alt-Ergo driver *)
% let alt_ergo_driver : Driver.driver =
% try
% Driver.load_driver env alt_ergo.Whyconf.driver
% with e ->
% eprintf "Failed to load driver for alt-ergo: %a@."
% Exn_printer.exn_printer e;
% exit 1
% \end{ocamlcode}
\lstinputlisting
{
logic
_
getdriver.ml
}
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{ocamlcode}
% (* calls Alt-Ergo *)
% let result1 : Call_provers.prover_result =
% Call_provers.wait_on_call
% (Driver.prove_task ~command:alt_ergo.Whyconf.command
% alt_ergo_driver task1 ()) ()
% (* prints Alt-Ergo answer *)
% let () = printf "@[On task 1, alt-ergo answers %a@]@."
% Call_provers.print_prover_result result1
% \end{ocamlcode}
\lstinputlisting
{
logic
_
callprover.ml
}
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
...
...
@@ -232,19 +173,6 @@ corresponding to these kinds of answers:
\end{itemize}
Here is thus another way of calling the Alt-Ergo prover, on our second
task.
% \begin{ocamlcode}
% let result2 : Call_provers.prover_result =
% Call_provers.wait_on_call
% (Driver.prove_task ~command:alt_ergo.Whyconf.command
% ~timelimit:10
% alt_ergo_driver task2 ()) ()
% let () =
% printf "@[On task 2, alt-ergo answers %a in %5.2f seconds@."
% Call_provers.print_prover_answer
% result1.Call_provers.pr_answer
% result1.Call_provers.pr_time
% \end{ocamlcode}
\lstinputlisting
{
logic
_
calltimelimit.ml
}
The output of our program is now as follows.
\begin{verbatim}
...
...
@@ -262,65 +190,29 @@ 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
{
sec:library
}
).
\begin{ocamlcode}
let two : Term.term =
Term.t
_
const (Number.ConstInt (Number.int
_
const
_
dec "2"))
let four : Term.term =
Term.t
_
const (Number.ConstInt (Number.int
_
const
_
dec "4"))
let int
_
theory : Theory.theory =
Env.read
_
theory env ["int"] "Int"
let plus
_
symbol : Term.lsymbol =
Theory.ns
_
find
_
ls int
_
theory.Theory.th
_
export [Ident.infix "+"]
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{ocamlcode}
\lstinputlisting
{
logic
_
buildfmla.ml
}
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{ocamlcode}
let two
_
plus
_
two : Term.term =
Term.fs
_
app plus
_
symbol [two;two] Ty.ty
_
int
\end{ocamlcode}
\lstinputlisting
{
logic
_
buildtermalt.ml
}
When building a task with this formula, we need to declare that we use
theory
\texttt
{
Int
}
:
\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{ocamlcode}
\lstinputlisting
{
logic
_
buildtaskimport.ml
}
\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{ocamlcode}
let zero : Term.term =
Term.t
_
const (Number.ConstInt (Number.int
_
const
_
dec "0"))
let mult
_
symbol : Term.lsymbol =
Theory.ns
_
find
_
ls int
_
theory.Theory.th
_
export [Ident.infix "*"]
let ge
_
symbol : Term.lsymbol =
Theory.ns
_
find
_
ls int
_
theory.Theory.th
_
export [Ident.infix ">="]
\end{ocamlcode}
\lstinputlisting
{
logic
_
quantfmla1.ml
}
The next step is to introduce the variable
$
x
$
with the type int.
\begin{ocamlcode}
let var
_
x : Term.vsymbol =
Term.create
_
vsymbol (Ident.id
_
fresh "x") Ty.ty
_
int
\end{ocamlcode}
\lstinputlisting
{
logic
_
quantfmla2.ml
}
The formula
$
x
*
x
\geq
0
$
is obtained as in the previous example.
\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{ocamlcode}
\lstinputlisting
{
logic
_
quantfmla3.ml
}
To quantify on
$
x
$
, we use the appropriate smart constructor as follows.
\begin{ocamlcode}
let fmla4 : Term.term = Term.t
_
forall
_
close [var
_
x] [] fmla4
_
aux
\end{ocamlcode}
\lstinputlisting
{
logic
_
quantfmla4.ml
}
\section
{
Building Theories
}
...
...
@@ -333,76 +225,37 @@ be done by a sequence of calls:
\end{itemize}
Creation of a theory named
\verb
|
My_theory
|
is done by
\begin{ocamlcode}
let my
_
theory : Theory.theory
_
uc =
Theory.create
_
theory (Ident.id
_
fresh "My
_
theory")
\end{ocamlcode}
\lstinputlisting
{
logic
_
buildth1.ml
}
First let us add formula 1 above as a goal:
\begin{ocamlcode}
let decl
_
goal1 : Decl.decl =
Decl.create
_
prop
_
decl Decl.Pgoal goal
_
id1 fmla1
let my
_
theory : Theory.theory
_
uc =
Theory.add
_
decl my
_
theory decl
_
goal1
\end{ocamlcode}
\lstinputlisting
{
logic
_
buildth2.ml
}
Note that we reused the goal identifier
\verb
|
goal_id1
|
that we
already defined to create task 1 above.
Adding formula 2 needs to add the declarations of predicate variables A
and B first:
\begin{ocamlcode}
let my
_
theory : Theory.theory
_
uc =
Theory.add
_
param
_
decl my
_
theory prop
_
var
_
A
let my
_
theory : Theory.theory
_
uc =
Theory.add
_
param
_
decl my
_
theory prop
_
var
_
B
let decl
_
goal2 : Decl.decl =
Decl.create
_
prop
_
decl Decl.Pgoal goal
_
id2 fmla2
let my
_
theory : Theory.theory
_
uc = Theory.add
_
decl my
_
theory decl
_
goal2
\end{ocamlcode}
\lstinputlisting
{
logic
_
buildth3.ml
}
Adding formula 3 is a bit more complex since it uses integers, thus it
requires to ``use'' the theory
\verb
|
int.Int
|
. Using a theory is
indeed not a primitive operation in the API: it must be done by a
combination of an ``export'' and the creation of a namespace. We
provide a helper function for that:
\begin{ocamlcode}
(* [use th1 th2] insert the equivalent of a "use import th2" in
theory th1 under construction *)
let use th1 th2 =
let name = th2.Theory.th
_
name in
Theory.close
_
namespace
(Theory.use
_
export
(Theory.open
_
namespace th1 name.Ident.id
_
string) th2) true
\end{ocamlcode}
\lstinputlisting
{
logic
_
buildth4.ml
}
Addition of formula 3 is then
\begin{ocamlcode}
let my
_
theory : Theory.theory
_
uc = use my
_
theory int
_
theory
let decl
_
goal3 : Decl.decl =
Decl.create
_
prop
_
decl Decl.Pgoal goal
_
id3 fmla3
let my
_
theory : Theory.theory
_
uc =
Theory.add
_
decl my
_
theory decl
_
goal3
\end{ocamlcode}
\lstinputlisting
{
logic
_
buildth5.ml
}
Addition of goal 4 is nothing more complex:
\begin{ocamlcode}
let decl
_
goal4 : Decl.decl =
Decl.create
_
prop
_
decl Decl.Pgoal goal
_
id4 fmla4
let my
_
theory :
Theory.theory
_
uc = Theory.add
_
decl my
_
theory decl
_
goal4
\end{ocamlcode}
\lstinputlisting
{
logic
_
buildth6.ml
}
Finally, we close our theory under construction as follows.
\begin{ocamlcode}
let my
_
theory : Theory.theory = Theory.close
_
theory my
_
theory
\end{ocamlcode}
\lstinputlisting
{
logic
_
buildth7.ml
}
We can inspect what we did by printing that theory:
\begin{ocamlcode}
let () = printf "@[theory is:@
\n
%a@]@." Pretty.print_theory my_theory
\end{ocamlcode}
\lstinputlisting
{
logic
_
printtheory.ml
}
which outputs
\begin{verbatim}
theory is:
my new theory is as follows:
theory My
_
theory
(* use BuiltIn *)
...
...
@@ -424,23 +277,12 @@ end
From a theory, one can compute at once all the proof tasks it contains
as follows:
\begin{ocamlcode}
let my
_
tasks : Task.task list =
List.rev (Task.split
_
theory my
_
theory None None)
\end{ocamlcode}
\lstinputlisting
{
logic
_
splittheory.ml
}
Note that the tasks are returned in reverse order, so we reverse the
list above.
We can check our generated tasks by printing them:
\begin{ocamlcode}
let () =
printf "Tasks are:@.";
let
_
=
List.fold
_
left
(fun i t -> printf "Task
%d: %a@." i Pretty.print_task t; i+1)
1 my
_
tasks
in ()
\end{ocamlcode}
\lstinputlisting
{
logic
_
printalltasks.ml
}
One can run provers on those tasks exactly as we did above.
...
...
examples/use_api/logic.ml
View file @
8b67eba7
...
...
@@ -159,22 +159,26 @@ An arithmetic goal: 2+2 = 4
*)
(* BEGIN{buildfmla} *)
let
two
:
Term
.
term
=
Term
.
t_nat_const
2
let
four
:
Term
.
term
=
Term
.
t_nat_const
4
let
int_theory
:
Theory
.
theory
=
Env
.
read_theory
env
[
"int"
]
"Int"
let
plus_symbol
:
Term
.
lsymbol
=
Theory
.
ns_find_ls
int_theory
.
Theory
.
th_export
[
"infix +"
]
let
two_plus_two
:
Term
.
term
=
Term
.
fs_app
plus_symbol
[
two
;
two
]
Ty
.
ty_int
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{buildfmla} *)
(* BEGIN{buildtermalt} *)
let
two_plus_two
:
Term
.
term
=
Term
.
fs_app
plus_symbol
[
two
;
two
]
Ty
.
ty_int
(* END{buildtermalt} *)
(* BEGIN{buildtaskimport} *)
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{buildtaskimport} *)
(*
let () = printf "@[task 3 created:@\n%a@]@." Pretty.print_task task3
...
...
@@ -191,21 +195,28 @@ let () = printf "@[On task 3, alt-ergo answers %a@."
Call_provers
.
print_prover_result
result3
(* quantifiers: let's build "forall x:int. x*x >= 0" *)
(* BEGIN{quantfmla1} *)
let
zero
:
Term
.
term
=
Term
.
t_nat_const
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{quantfmla1} *)
(* BEGIN{quantfmla2} *)
let
var_x
:
Term
.
vsymbol
=
Term
.
create_vsymbol
(
Ident
.
id_fresh
"x"
)
Ty
.
ty_int
(* END{quantfmla2} *)
(* BEGIN{quantfmla3} *)
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{quantfmla3} *)
(* BEGIN{quantfmla4} *)
let
fmla4
:
Term
.
term
=
Term
.
t_forall_close
[
var_x
]
[]
fmla4_aux
(* END{quantfmla4} *)
let
task4
=
None
let
task4
=
Task
.
use_export
task4
int_theory
...
...
@@ -226,53 +237,76 @@ let () = printf "@[On task 4, alt-ergo answers %a@."
(* create a theory *)
let
()
=
printf
"@[creating theory 'My_theory'@]@."
(* BEGIN{buildth1} *)
let
my_theory
:
Theory
.
theory_uc
=
Theory
.
create_theory
(
Ident
.
id_fresh
"My_theory"
)
(* END{buildth1} *)
(* add declarations of goals *)
let
()
=
printf
"@[adding goal 1@]@."
let
decl_goal1
:
Decl
.
decl
=
Decl
.
create_prop_decl
Decl
.
Pgoal
goal_id1
fmla1
(* BEGIN{buildth2} *)
let
decl_goal1
:
Decl
.
decl
=
Decl
.
create_prop_decl
Decl
.
Pgoal
goal_id1
fmla1
let
my_theory
:
Theory
.
theory_uc
=
Theory
.
add_decl
my_theory
decl_goal1
(* END{buildth2} *)
let
()
=
printf
"@[adding goal 2@]@."
let
my_theory
:
Theory
.
theory_uc
=
Theory
.
add_param_decl
my_theory
prop_var_A
let
my_theory
:
Theory
.
theory_uc
=
Theory
.
add_param_decl
my_theory
prop_var_B
(* BEGIN{buildth3} *)
let
my_theory
:
Theory
.
theory_uc
=
Theory
.
add_param_decl
my_theory
prop_var_A
let
my_theory
:
Theory
.
theory_uc
=
Theory
.
add_param_decl
my_theory
prop_var_B
let
decl_goal2
:
Decl
.
decl
=
Decl
.
create_prop_decl
Decl
.
Pgoal
goal_id2
fmla2
let
my_theory
:
Theory
.
theory_uc
=
Theory
.
add_decl
my_theory
decl_goal2
(* END{buildth3} *)
(* helper function: [use th1 th2] insert the equivalent of a "use import th2"
in theory th1 under construction *)
(* BEGIN{buildth4} *)
(* helper function: [use th1 th2] insert the equivalent of a
"use import th2" in theory th1 under construction *)
let
use
th1
th2
=
let
name
=
th2
.
Theory
.
th_name
in
Theory
.
close_namespace
(
Theory
.
use_export
(
Theory
.
open_namespace
th1
name
.
Ident
.
id_string
)
th2
)
(
Theory
.
use_export
(
Theory
.
open_namespace
th1
name
.
Ident
.
id_string
)
th2
)
true
(* END{buildth4} *)
let
()
=
printf
"@[adding goal 3@]@."
(* use import int.Int *)
(* BEGIN{buildth5} *)
let
my_theory
:
Theory
.
theory_uc
=
use
my_theory
int_theory
let
decl_goal3
:
Decl
.
decl
=
Decl
.
create_prop_decl
Decl
.
Pgoal
goal_id3
fmla3
let
decl_goal3
:
Decl
.
decl
=
Decl
.
create_prop_decl
Decl
.
Pgoal
goal_id3
fmla3
let
my_theory
:
Theory
.
theory_uc
=
Theory
.
add_decl
my_theory
decl_goal3
(* END{buildth5} *)
let
()
=
printf
"@[adding goal 4@]@."
let
decl_goal4
:
Decl
.
decl
=
Decl
.
create_prop_decl
Decl
.
Pgoal
goal_id4
fmla4
(* BEGIN{buildth6} *)
let
decl_goal4
:
Decl
.
decl
=
Decl
.
create_prop_decl
Decl
.
Pgoal
goal_id4
fmla4
let
my_theory
:
Theory
.
theory_uc
=
Theory
.
add_decl
my_theory
decl_goal4
(* END{buildth6} *)
(* closing the theory *)
(* BEGIN{buildth7} *)
let
my_theory
:
Theory
.
theory
=
Theory
.
close_theory
my_theory
(* END{buildth7} *)
(* printing the result *)
let
()
=
printf
"@[theory is:@
\n
%a@]@."
Pretty
.
print_theory
my_theory
(* BEGIN{printtheory} *)
let
()
=
printf
"@[my new theory is as follows:@
\n
@
\n
%a@]@."
Pretty
.
print_theory
my_theory
(* END{printtheory} *)
(* getting set of task from a theory *)
(* BEGIN{splittheory} *)
let
my_tasks
:
Task
.
task
list
=
List
.
rev
(
Task
.
split_theory
my_theory
None
None
)
(* END{splittheory} *)
(* BEGIN{printalltasks} *)
let
()
=
printf
"Tasks are:@."
;
let
_
=
...
...
@@ -280,6 +314,7 @@ let () =
(
fun
i
t
->
printf
"Task %d: %a@."
i
Pretty
.
print_task
t
;
i
+
1
)
1
my_tasks
in
()
(* END{printalltasks} *)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment