Commit a69c569a authored by Johannes Kanig's avatar Johannes Kanig

merge with master

parents e4dff854 366f7e3a
......@@ -160,7 +160,7 @@ LIB_UTIL = config bigInt util opt lists strings \
LIB_CORE = ident ty term pattern decl theory \
task pretty dterm env trans printer model_parser
LIB_DRIVER = prove_client call_provers driver_ast driver_parser driver_lexer driver \
LIB_DRIVER = call_provers driver_ast driver_parser driver_lexer driver \
whyconf autodetection \
parse_smtv2_model_parser parse_smtv2_model_lexer parse_smtv2_model
......@@ -236,10 +236,13 @@ src/session/compress.ml: config.status src/session/compress_none.ml
cp src/session/compress_none.ml $@
endif
<<<<<<< HEAD
src/driver/vc_client.o: src/driver/vc_client.c
gcc -O -mms-bitfields -Wall -Wno-unused -c -I$(OCAMLLIB) -fPIC $^
mv $(CURDIR)/vc_client.o $@
=======
>>>>>>> lri-master
# hide deprecated warnings for strings
src/util/strings.cmo:: WARNINGS:=$(WARNINGS)-3
......@@ -250,11 +253,11 @@ src/util/strings.cmx:: WARNINGS:=$(WARNINGS)-3
byte: lib/why3/why3.cma
opt: lib/why3/why3.cmxa
lib/why3/why3.cma: lib/why3/why3.cmo src/driver/vc_client.o
lib/why3/why3.cma: lib/why3/why3.cmo
$(if $(QUIET),@echo 'Linking $@' &&) \
$(OCAMLC) -a $(BFLAGS) -o $@ $^
lib/why3/why3.cmxa: lib/why3/why3.cmx src/driver/vc_client.o
lib/why3/why3.cmxa: lib/why3/why3.cmx
$(if $(QUIET),@echo 'Linking $@' &&) \
$(OCAMLOPT) -a $(OFLAGS) -o $@ $^
......@@ -559,7 +562,6 @@ clean_old_install::
install_no_local::
cp -f bin/why3.@OCAMLBEST@ $(BINDIR)/why3$(EXE)
cp -f bin/why3server$(EXE) $(BINDIR)/why3$(EXE)
cp -f bin/why3config.@OCAMLBEST@ $(TOOLDIR)/why3config$(EXE)
cp -f bin/why3execute.@OCAMLBEST@ $(TOOLDIR)/why3execute$(EXE)
cp -f bin/why3extract.@OCAMLBEST@ $(TOOLDIR)/why3extract$(EXE)
......@@ -615,51 +617,6 @@ clean::
%.type: %.mlw bin/why3ide.opt
bin/why3.opt --type-only $*.mlw
##############
# Why3server #
##############
SERVER_MODULES:= logging arraylist options queue readbuf request writebuf server_main
SERVER_C:= $(addprefix src/tools/, $(addsuffix .c, $(SERVER_MODULES)))
SERVER_H:= $(addprefix src/tools/, $(addsuffix .h, $(SERVER_MODULES)))
SERVER_O:= $(addprefix src/tools/, $(addsuffix .o, $(SERVER_MODULES)))
opt: bin/why3server$(EXE)
bin/why3server$(EXE): $(SERVER_O)
gcc -o $@ $^
%.o: %.c %.h
gcc -c -Wall -g -o $@ $<
%.o: %.c
gcc -c -Wall -g -o $@ $<
src/tools/main.o:: src/tools/server-unix.c src/tools/server-win.c
install_no_local::
cp -f bin/why3server$(EXE) $(BINDIR)/why3server$(EXE)
clean::
rm -f $(SERVER_O)
install_spark2014:
mkdir -p $(BINDIR)
mkdir -p $(DATADIR)/why3
mkdir -p $(DATADIR)/why3/theories
mkdir -p $(DATADIR)/why3/drivers
mkdir -p $(DATADIR)/why3/modules
mkdir -p $(DATADIR)/why3/libs
cp -f theories/*.why $(DATADIR)/why3/theories
cp -f modules/*.mlw $(DATADIR)/why3/modules
cp -f drivers/*.drv drivers/*.gen drivers/*.aux $(DATADIR)/why3/drivers
cp -f share/why3session.dtd $(DATADIR)/why3
cp -f bin/why3server$(EXE) $(BINDIR)/why3server$(EXE)
cp -f bin/gnatwhy3.@OCAMLBEST@ $(BINDIR)/gnatwhy3$(EXE)
cp -f bin/why3realize.@OCAMLBEST@ $(BINDIR)/why3realize$(EXE)
cp -f bin/why3config.@OCAMLBEST@ $(BINDIR)/why3config$(EXE)
cp -f share/provers-detection-data.conf $(DATADIR)/why3/
cp -rf lib/coq $(DATADIR)/why3/libs
##########
# gallery
##########
......
......@@ -336,12 +336,20 @@ DONE * sauvegarde de la configuration : à quel endroit dans l'IDE ?
Fedora package
* produce the Why3 part of Toccata gallery
(TODO: add the procedure here)
add also a tar.gz and a ZIP file of it: this is done by doing
"make gallery-files" in the sources of the Toccata web pages
* Once the OPAM package is pulled in the main OPAM repository: a
nnounce the distrib
- have GALLERYDIR set to the sub-directory gallery/ of the git sources
of the Toccata web site, e.g.
export GALLERYDIR=/users/vals/filliatr/toccata/web/gallery
- in Why3 sources, do "make gallery"; it exports to GALLERYDIR all
Why3 programs for which there is a session
- now move to the Toccata web site sources, and
- update web/gallery/examples.rc to include new examples
- "git add" the files for these new examples (those currently untracked
in git) or simply remove them if they should not go on-line
- do "make" in web/gallery/
- do "make install-gallery" in web/
* Once the OPAM package is pulled in the main OPAM repository:
announce the distrib
What to put in the announcement: see New Features above
......
......@@ -6,6 +6,8 @@
| formula "&&" formula ; asymmetric conj.
| formula "\/" formula ; disjunction
| formula "||" formula ; asymmetric disj.
| formula "by" formula ; proof indication
| formula "so" formula ; consequence indication
| "not" formula ; negation
| lqualid ; symbol
| prefix-op term ;
......
......@@ -128,6 +128,7 @@ associativities, from lowest to greatest priority:
\texttt{if then else} / \texttt{let in} & -- \\
label & -- \\
\texttt{->} / \texttt{<->} & right \\
\texttt{by} / \texttt{so} & right \\
\verb!\/! / \verb!||! & right \\
\verb|/\| / \verb!&&! & right \\
\texttt{not} & -- \\
......@@ -156,6 +157,11 @@ transformations. For instance, \texttt{split} transforms the goal
\verb|A && B| into subgoals \verb|A| and \verb|A -> B|. Similarly, it
transforms \verb!not (A || B)! into subgoals \verb|not A| and
\verb|not ((not A) /\ B)|.
The \texttt{by}/\texttt{so} connectives are proof indications. They are
logically equivalent to their first argument, but may affect the result
of some transformations. For instance, the \texttt{split\_goal}
transformations interpret those connectives as introduction of logical cuts
(see~\ref{tech:trans:split} for details).
\subsection{Theories}
......
......@@ -423,42 +423,184 @@ P(t)
is the same as above but it applies only in the goal.
\index{simplify-trivial-quantification-in-goal@\verb+simplify_trivial_quantification_in_goal+}
\item[split\_premise]
splits conjunctive premises.
\item[split\_premise] replaces axioms in conjunctive form
by an equivalent collection of axioms.
In absence of case analysis labels (see \texttt{split\_goal} for details),
the number of axiom generated per initial axiom is
linear in the size of that initial axiom.
\index{split-premise@\verb+split_premise+}
\item[split\_premise\_full]: This transformation is similar to \texttt{split\_premise}, but also converts the axioms to conjunctive normal form. The number of axioms generated per initial axiom may be exponential in the size of the initial axiom.
\index{split-premise-full@\verb+split_premise_full+}
\end{description}
\subsection{Other Splitting Transformations}
\subsection{Other Splitting Transformations}~\label{tech:trans:split}
\begin{description}
\item[full\_split\_all]
performs both \texttt{split\_premise} and \texttt{full\_split\_goal}.
\index{full-split-all@\verb+full_split_all+}
\item[full\_split\_goal] puts the goal in a conjunctive form,
returns the corresponding set of subgoals. The number of subgoals
generated may be exponential in the size of the initial goal.
\index{full-split-goal@\verb+full_split_goal+}
\item[simplify\_formula\_and\_task] is the same as \texttt{simplify\_formula}
but it also removes the goal if it is equivalent to true.
\index{full-split-all@\verb+full_split_all+}
\index{simplify-formula-and-task@\verb+simplify_formula_and_task+}
\item[split\_goal]: if the goal is a conjunction of goals, returns the
corresponding set of subgoals. In absence of case analysis labels,
the number of subgoals generated is linear in the size of the initial goal.
\paragraph{Behavior on asymmetric connectives and
\texttt{by}/\texttt{so}}
The transformation treat specially asymmetric and
\texttt{by}/\texttt{so} connectives. Asymmetric conjunction
\verb|A && B| in goal position is handled as syntactic sugar for
\verb|A /\ (A -> B)|. The conclusion of the first subgoal can then
be used to prove the second one.
Asymmetric disjunction \verb+A || B+ in hypothesis position is handled as
syntactic sugar for \verb|A \/ ((not A) /\ B)|.
In particular, a case analysis on such hypothesis would give the negation of
the first hypothesis in the second case.
The \texttt{by} connective is treated as a proof indication. In
hypothesis position, \verb|A by B| is treated as if it were
syntactic sugar for its regular interpretation \verb|A|. In goal
position, it is treated as if \verb|B| was an intermediate step for
proving \verb|A|. \verb|A by B| is then replaced by \verb|B| and the
transformation also generates a side-condition subgoal \verb|B -> A|
representing the logical cut.
Although splitting stops at disjunctive points like symmetric
disjunction and left-hand sides of implications, the occurrences of
the \texttt{by} connective are not restricted. For instance:
\begin{itemize}
\item Splitting
\begin{whycode}
goal G : (A by B) && C
\end{whycode}
generates the subgoals
\begin{whycode}
goal G1 : B
goal G2 : A -> C
goal G3 : B -> A (* side-condition *)
\end{whycode}
\item Splitting
\begin{whycode}
goal G : (A by B) \/ (C by D)
\end{whycode}
generates
\begin{whycode}
goal G1 : B \/ D
goal G2 : B -> A (* side-condition *)
goal G3 : D -> C (* side-condition *)
\end{whycode}
\item Splitting
\begin{whycode}
goal G : (A by B) || (C by D)
\end{whycode}
generates
\begin{whycode}
goal G1 : B || D
goal G2 : B -> A (* side-condition *)
goal G3 : B || (D -> C) (* side-condition *)
\end{whycode}
Note that due to the asymmetric disjunction, the disjunction is kept in the
second side-condition subgoal.
\item Splitting
\begin{whycode}
goal G : exists x. P x by x = 42
\end{whycode}
generates
\begin{whycode}
goal G1 : exists x. x = 42
goal G2 : forall x. x = 42 -> P x (* side-condition *)
\end{whycode}
Note that in the side-condition subgoal, the context is universally closed.
\end{itemize}
The \texttt{so} connective plays a similar role in hypothesis position, as it serves as a consequence indication. In goal position, \verb|A so B| is treated as if it were syntactic sugar for its regular interpretation \verb|A|. In hypothesis position, it is treated as if both \verb|A| and \verb|B| were true because \verb|B| is a consequence of \verb|A|. \verb|A so B| is replaced by \verb|A /\ B| and the transformation also generates a side-condition subgoal \verb|A -> B| corresponding to the consequence relation between formula.
As for the \texttt{by} connective, occurrences of \texttt{so} are unrestricted.
For instance:
\begin{itemize}
\item Splitting
\begin{whycode}
goal G : (((A so B) \/ C) -> D) && E
\end{whycode}
generates
\begin{whycode}
goal G1 : ((A /\ B) \/ C) -> D
goal G2 : (A \/ C -> D) -> E
goal G3 : A -> B (* side-condition *)
\end{whycode}
\item Splitting
\begin{whycode}
goal G : A by exists x. P x so Q x so R x by T x
(* reads: A by (exists x. P x so (Q x so (R x by T x))) *)
\end{whycode}
\begin{whycode}
goal G1 : exists x. P x
goal G2 : forall x. P x -> Q x (* side-condition *)
goal G3 : forall x. P x -> Q x -> T x (* side-condition *)
goal G4 : forall x. P x -> Q x -> T x -> R x (* side-condition *)
goal G5 : (exists x. P x /\ Q x /\ R x) -> A (* side-condition *)
\end{whycode}
In natural language, this corresponds to the following proof schema
for \verb|A|: There exists a \verb|x| for which \verb|P| holds. Then,
for that witness \verb|Q| and \verb|R| also holds. The last one holds
because \verb|T| holds as well. And from those three conditions on
\verb|x|, we can deduce \verb|A|.
\end{itemize}
\paragraph{Labels controlling the transformation}
The transformations in the split family can be controlled by using
labels on formulas.
The label \verb|"stop_split"| can be used to block the splitting of a
formula. The label is removed after blocking, so applying the
transformation a second time will split the formula. This is can be
used to decompose the splitting process in several steps. Also, if a
formula with this label is found in non-goal position, its
\texttt{by}/\texttt{so} proof indication will be erased by the
transformation. In a sense, formulas tagged by \verb|"stop_split"| are
handled as if they were local lemmas.
The label \verb|"case_split"| can be used to force case analysis on hypotheses.
For instance, applying \texttt{split\_goal} on
\begin{whycode}
goal G : ("case_split" A \/ B) -> C
\end{whycode}
generates the subgoals
\begin{whycode}
goal G1 : A -> C
goal G2 : B -> C
\end{whycode}
Without the label, the transformation do nothing because undesired case analysis
may easily lead to an exponential blow-up.
Note that the precise behavior of splitting transformation in presence of
the \verb|"case_split"| is not yet specified
and is likely to change in future versions.
\index{split-goal@\verb+split_goal+}
\item[split\_all]
performs both \texttt{split\_premise} and \texttt{split\_goal}.
\index{split-all@\verb+split_all+}
\item[split\_goal] if the goal is a conjunction of goals, returns the
corresponding set of subgoals. The number of subgoals generated is linear in
the size of the initial goal.
\index{split-goal@\verb+split_goal+}
\item[split\_intro]
moves the antecedents into the premises when a goal is an implication.
\item[split\_intro]: Composition of \texttt{split\_goal} and \texttt{introduce\_premises}.
\index{split-intro@\verb+split_intro+}
\item[split\_goal\_full]: This transformation has a behavior similar
to \texttt{split\_goal}, but also converts the goal to conjunctive normal form.
The number of subgoals generated may be exponential in the size of the initial goal.
\index{split-goal-full@\verb+split_goal_full+}
\item[split\_all\_full]
performs both \texttt{split\_premise} and \texttt{split\_goal\_full}.
\index{split-all-full@\verb+split_all_full+}
\end{description}
......@@ -467,4 +609,3 @@ P(t)
%%% TeX-PDF-mode: t
%%% TeX-master: "manual"
%%% End:
This diff is collapsed.
Child_is_son_or_daughter: THEORY
BEGIN
% do not edit above this line
% surround new declarations you insert below with blank lines
% Why3 person
person: TYPE+
......
......@@ -2,7 +2,7 @@
<!DOCTYPE why3session PUBLIC "-//Why3//proof session v5//EN"
"http://why3.lri.fr/why3session.dtd">
<why3session shape_version="4">
<prover id="0" name="Isabelle" version="2015" timelimit="5" steplimit="1" memlimit="4000"/>
<prover id="0" name="Isabelle" version="2015" timelimit="5" steplimit="1" memlimit="0"/>
<prover id="1" name="CVC4" version="1.2" timelimit="60" steplimit="1" memlimit="1000"/>
<prover id="2" name="Zenon" version="0.8.0" timelimit="5" steplimit="1" memlimit="1000"/>
<prover id="3" name="CVC3" version="2.4.1" timelimit="5" steplimit="1" memlimit="0"/>
......@@ -16,7 +16,7 @@
<prover id="11" name="Simplify" version="1.5.4" timelimit="3" steplimit="1" memlimit="1000"/>
<prover id="12" name="Yices" version="1.0.38" timelimit="5" steplimit="1" memlimit="0"/>
<prover id="13" name="Zenon" version="0.7.1" timelimit="5" steplimit="1" memlimit="4000"/>
<prover id="14" name="Alt-Ergo" version="1.01" timelimit="5" memlimit="4000"/>
<prover id="14" name="Alt-Ergo" version="1.01" timelimit="5" steplimit="1" memlimit="4000"/>
<prover id="15" name="Metis" version="2.3" timelimit="5" steplimit="1" memlimit="1000"/>
<prover id="16" name="Z3" version="3.2" timelimit="5" steplimit="1" memlimit="0"/>
<prover id="17" name="Alt-Ergo" version="0.95.2" timelimit="60" steplimit="1" memlimit="1000"/>
......@@ -30,10 +30,10 @@
<prover id="25" name="Alt-Ergo" version="1.00.prv" timelimit="5" steplimit="1" memlimit="1000"/>
<prover id="26" name="Zenon Modulo" version="0.4.1" timelimit="5" steplimit="1" memlimit="1000"/>
<prover id="27" name="Coq" version="8.4pl6" timelimit="5" steplimit="1" memlimit="4000"/>
<prover id="28" name="Z3" version="4.4.1" timelimit="5" memlimit="4000"/>
<prover id="28" name="Z3" version="4.4.1" timelimit="5" steplimit="1" memlimit="4000"/>
<file name="../genealogy.why" expanded="true">
<theory name="Genealogy" sum="35e1439432a79e05534b2c5cf39ad9dc" expanded="true">
<goal name="Child_is_son_or_daughter" expanded="true">
<theory name="Genealogy" sum="35e1439432a79e05534b2c5cf39ad9dc">
<goal name="Child_is_son_or_daughter">
<proof prover="0" edited="genealogy_Genealogy_Child_is_son_or_daughter_1.xml"><result status="valid" time="6.55"/></proof>
<proof prover="2"><result status="valid" time="0.02"/></proof>
<proof prover="3"><result status="valid" time="0.00"/></proof>
......@@ -60,8 +60,8 @@
<proof prover="27" edited="genealogy_Genealogy_Child_is_son_or_daughter_1.v"><result status="valid" time="0.80"/></proof>
<proof prover="28"><result status="valid" time="0.01"/></proof>
</goal>
<goal name="Sibling_sym" expanded="true">
<proof prover="0" edited="genealogy_Genealogy_Sibling_sym_1.xml"><result status="valid" time="6.09"/></proof>
<goal name="Sibling_sym">
<proof prover="0" edited="genealogy_Genealogy_Sibling_sym_1.xml"><result status="valid" time="7.12"/></proof>
<proof prover="1"><result status="valid" time="0.00"/></proof>
<proof prover="3"><result status="valid" time="0.00"/></proof>
<proof prover="4"><result status="valid" time="0.00"/></proof>
......@@ -87,8 +87,8 @@
<proof prover="26"><result status="valid" time="0.02"/></proof>
<proof prover="28"><result status="valid" time="0.00"/></proof>
</goal>
<goal name="Sibling_is_brother_or_sister" expanded="true">
<proof prover="0" edited="genealogy_Genealogy_Sibling_is_brother_or_sister_1.xml"><result status="valid" time="6.19"/></proof>
<goal name="Sibling_is_brother_or_sister">
<proof prover="0" edited="genealogy_Genealogy_Sibling_is_brother_or_sister_1.xml"><result status="valid" time="7.32"/></proof>
<proof prover="2"><result status="valid" time="0.03"/></proof>
<proof prover="3"><result status="valid" time="0.00"/></proof>
<proof prover="4"><result status="valid" time="0.00"/></proof>
......@@ -112,8 +112,8 @@
<proof prover="26"><result status="valid" time="0.01"/></proof>
<proof prover="28"><result status="valid" time="0.01"/></proof>
</goal>
<goal name="Grandparent_is_grandfather_or_grandmother" expanded="true">
<proof prover="0" edited="genealogy_Genealogy_Grandparent_is_grandfather_or_grandmother_1.xml"><result status="valid" time="6.50"/></proof>
<goal name="Grandparent_is_grandfather_or_grandmother">
<proof prover="0" edited="genealogy_Genealogy_Grandparent_is_grandfather_or_grandmother_1.xml"><result status="valid" time="7.48"/></proof>
<proof prover="1"><result status="valid" time="0.01"/></proof>
<proof prover="3"><result status="valid" time="0.00"/></proof>
<proof prover="4"><result status="valid" time="0.01"/></proof>
......@@ -138,7 +138,7 @@
<proof prover="26"><result status="valid" time="0.02"/></proof>
<proof prover="28"><result status="valid" time="0.01"/></proof>
</goal>
<goal name="Grandfather_male" expanded="true">
<goal name="Grandfather_male">
<proof prover="1"><result status="valid" time="0.00"/></proof>
<proof prover="3"><result status="valid" time="0.00"/></proof>
<proof prover="4"><result status="valid" time="0.00"/></proof>
......@@ -164,7 +164,7 @@
<proof prover="26"><result status="valid" time="0.02"/></proof>
<proof prover="28"><result status="valid" time="0.00"/></proof>
</goal>
<goal name="Grandmother_female" expanded="true">
<goal name="Grandmother_female">
<proof prover="1"><result status="valid" time="0.01"/></proof>
<proof prover="3"><result status="valid" time="0.00"/></proof>
<proof prover="4"><result status="valid" time="0.00"/></proof>
......@@ -190,7 +190,7 @@
<proof prover="26"><result status="valid" time="0.02"/></proof>
<proof prover="28"><result status="valid" time="0.00"/></proof>
</goal>
<goal name="Only_two_grandfathers" expanded="true">
<goal name="Only_two_grandfathers">
<proof prover="1"><result status="valid" time="0.01"/></proof>
<proof prover="3"><result status="valid" time="0.00"/></proof>
<proof prover="4"><result status="valid" time="0.01"/></proof>
......
......@@ -372,76 +372,3 @@ let wait_on_call pc =
let post_wait_call pc ret = pc.call ret
let prover_call_pid pc = pc.pid
let set_socket_name =
Prove_client.set_socket_name
type server_id = int
let gen_id =
let x = ref 0 in
fun () ->
incr x;
!x
type save_data =
{ vc_file : string;
is_temporary : bool;
limit : resource_limit;
res_parser : prover_result_parser;
printer_mapping : Printer.printer_mapping;
}
let regexs : (int, save_data) Hashtbl.t = Hashtbl.create 17
let prove_file_server ~res_parser ~command ~limit
~printer_mapping ?(inplace=false) ?(interactive=false) file =
let id = gen_id () in
let cmd, _, _ = actualcommand command ~use_why3cpulimit:false limit interactive file in
let saved_data =
{ vc_file = file;
is_temporary = not inplace;
limit = limit;
res_parser = res_parser;
printer_mapping = printer_mapping } in
Hashtbl.add regexs id saved_data;
let timelimit = get_time limit in
let memlimit = get_mem limit in
Prove_client.send_request ~id ~timelimit ~memlimit ~cmd;
id
let read_and_delete_file fn =
let cin = open_in fn in
let buf = Buffer.create 1024 in
try
while true do
Buffer.add_string buf (input_line cin);
Buffer.add_char buf '\n'
done;
assert false
with End_of_file ->
begin
close_in cin;
Sys.remove fn;
Buffer.contents buf
end
let handle_answer answer =
let id = answer.Prove_client.id in
let save = Hashtbl.find regexs id in
Hashtbl.remove regexs id;
if save.is_temporary then
Sys.remove save.vc_file;
let out = read_and_delete_file answer.Prove_client.out_file in
let ret = Unix.WEXITED answer.Prove_client.exit_code in
let printer_mapping = save.printer_mapping in
let ans =
parse_prover_run save.res_parser
answer.Prove_client.time
out ret answer.Prove_client.timeout save.limit
~printer_mapping
in
id, ans
let wait_for_server_result () =
List.map handle_answer (Prove_client.read_answers ())
......@@ -188,18 +188,3 @@ val post_wait_call : prover_call -> Unix.process_status -> post_prover_call
val prover_call_pid : prover_call -> int
(** Return the pid of the prover *)
val set_socket_name : string -> unit
type server_id = int
val prove_file_server :
res_parser : prover_result_parser ->
command : string ->
limit : resource_limit ->
printer_mapping : Printer.printer_mapping ->
?inplace : bool ->
?interactive : bool ->
string -> server_id
val wait_for_server_result : unit -> (server_id * prover_result) list
......@@ -257,6 +257,7 @@ let call_on_buffer ~command ~limit
~command ~limit ~res_parser:drv.drv_res_parser
~filename ~printer_mapping ?inplace ?interactive buffer
(** print'n'prove *)
exception NoPrinter
......@@ -322,8 +323,14 @@ let print_theory ?old drv fmt th =
let task = Task.use_export None th in
print_task ?old drv fmt task
let file_name_of_task ?old ?inplace drv task =
match old, inplace with
let prove_task_prepared ~command ~limit ?old ?inplace ?interactive drv task =
let buf = Buffer.create 1024 in
let fmt = formatter_of_buffer buf in
let old_channel = Opt.map open_in old in
let printer_mapping = print_task_prepared ?old:old_channel drv fmt task in
pp_print_flush fmt ();
Opt.iter close_in old_channel;
let filename = match old, inplace with
| Some fn, Some true -> fn
| _ ->
let pr = Task.task_goal task in
......@@ -332,15 +339,7 @@ let file_name_of_task ?old ?inplace drv task =
| None -> "" in
let fn = try Filename.chop_extension fn with Invalid_argument _ -> fn in
get_filename drv fn "T" pr.pr_name.id_string
let prove_task_prepared ~command ~limit ?old ?inplace ?interactive drv task =
let buf = Buffer.create 1024 in
let fmt = formatter_of_buffer buf in
let old_channel = Opt.map open_in old in
let filename = file_name_of_task ?old ?inplace drv task in
let printer_mapping = print_task_prepared ?old:old_channel drv fmt task in
pp_print_flush fmt ();
Opt.iter close_in old_channel;
in
let res =
call_on_buffer ~command ~limit
?inplace ?interactive ~filename ~printer_mapping drv buf in
......@@ -352,21 +351,6 @@ let prove_task ~command ~limit ?(cntexample=false) ?old
let task = prepare_task ~cntexample drv task in
prove_task_prepared ~command ~limit ?old ?inplace ?interactive drv task
let prove_task_server command ~limit ~cntexample ?old ?inplace drv task =
let task = prepare_task ~cntexample drv task in
let fn = file_name_of_task ?old ?inplace drv task in
let res_parser = drv.drv_res_parser in
let printer_mapping = get_default_printer_mapping in
match inplace with
| Some true ->
prove_file_server ~command ~res_parser ~limit ~printer_mapping ?inplace fn
| _ -> let fn, outc = Filename.open_temp_file "why_" ("_" ^ fn) in
let fmt = Format.formatter_of_out_channel outc in
let printer_mapping = print_task_prepared ?old:None drv fmt task in
close_out outc;
prove_file_server ~command ~res_parser ~limit ~printer_mapping fn
(* exception report *)
let string_of_qualid thl idl =
......
......@@ -70,12 +70,6 @@ val print_task_prepared :
?old : in_channel ->
driver -> Format.formatter -> Task.task -> Printer.printer_mapping
val prove_task_server : string ->
limit : Call_provers.resource_limit ->
cntexample:bool ->
?old:string -> ?inplace:bool -> driver -> Task.task ->
Call_provers.server_id
val prove_task_prepared :
command : string ->
limit : Call_provers.resource_limit ->
......
external client_connect : string -> unit = "c_client_connect"
external client_disconnect : unit -> unit = "c_client_disconnect"
external send_request_string : string -> unit = "c_send_request_string"
external read_from_client : unit -> string = "c_read_from_client"
type answer =
{
id : int;
exit_code : int;
time : float;
timeout : bool;
out_file : string;
}
let socket_name : string ref = ref ""
let set_socket_name s =
socket_name := s
let buf : Buffer.t = Buffer.create 1024
let connect () =
Buffer.clear buf;
client_connect !socket_name
let disconnect () =
client_disconnect ()
let send_request ~id ~timelimit ~memlimit ~cmd =
let buf = Buffer.create 128 in
Buffer.add_string buf (string_of_int id);
Buffer.add_char buf ';';
Buffer.add_string buf (string_of_int timelimit);
Buffer.add_char buf ';';
Buffer.add_string buf (string_of_int memlimit);
List.iter (fun x ->
Buffer.add_char buf ';';
Buffer.add_string buf x)
cmd;
Buffer.add_char buf '\n';
let s = Buffer.contents buf in
send_request_string s
let rec read_lines () =
let s = read_from_client () in
if String.contains s '\n' then begin
let s = Buffer.contents buf ^ s in
Buffer.clear buf;
let l = Strings.rev_split '\n' s in
match l with
| [] -> assert false
| [x] -> [x]
| (x::xs) as l ->
if x = "" then List.rev xs else
if x.[String.length x - 1] = '\n' then List.rev l
else begin
Buffer.add_string buf x;
List.rev xs
end
end else begin
Buffer.add_string buf s;
read_lines ()
end
let bool_of_timeout_string s =
if s = "1" then true else false
let read_answer s =
let l = Strings.split ';' s in
match l with
| id :: exit_s :: time_s :: timeout_s :: ( (_ :: _) as rest) ->
(* same trick we use in other parsing code. The file name may contain
';'. Luckily, the file name comes last, so we still split on ';', and
put the pieces back together afterwards *)
let out_file = Strings.join ";" rest in
{ id = int_of_string id;
out_file = out_file;
time = float_of_string time_s;
exit_code = int_of_string exit_s;
timeout = bool_of_timeout_string timeout_s;
}