1 (********************************************************************)
3 (* The Why3 Verification Platform / The Why3 Development Team *)
4 (* Copyright 2010-2023 -- Inria - CNRS - Paris-Saclay University *)
6 (* This software is distributed under the terms of the GNU Lesser *)
7 (* General Public License version 2.1, with the special exception *)
8 (* on linking described in file LICENSE. *)
10 (********************************************************************)
14 This file builds some MLW modules, using parse trees instead of direct
21 let config : Whyconf.config = Whyconf.init_config None
22 let main : Whyconf.main = Whyconf.get_main
config
23 let env : Env.env = Env.create_env
(Whyconf.loadpath
main)
40 let use_int_Int = use ~import
:false (["int";"Int"]) in
41 (* goal g : 2 + 2 = 4 *)
44 let four = tconst
4 in
45 let add_int = qualid
["Int";Ident.op_infix
"+"] in
46 let two_plus_two = tapp
add_int [two ; two] in
47 let eq_int = qualid
["Int";Ident.op_infix
"="] in
48 let goal_term = tapp
eq_int [four ; two_plus_two] in
49 Dprop
(Decl.Pgoal
, ident
"g", goal_term)
51 (ident
"M1",[use_int_Int ; g])
67 let eq_symb = qualid
[Ident.op_infix
"="]
68 let int_type_id = qualid
["int"]
69 let int_type = PTtyapp
(int_type_id,[])
70 let mul_int = qualid
["Int";Ident.op_infix
"*"]
74 let use_int_Int = use ~import
:false (["int";"Int"]) in
77 let id_x = ident
"x" in
78 let pre = tapp
eq_symb [tvar
(Qident
id_x); tconst
6] in
79 let result = ident
"result" in
80 let post = tapp
eq_symb [tvar
(Qident
result); tconst
42] in
83 sp_post
= [Loc.dummy_position
,[pat_var
result,post]];
94 let body = eapp
mul_int [evar
(Qident
id_x); econst
7] in
96 Efun
(one_binder ~pty
:int_type "x", None
, pat Pwild
,
97 Ity.MaskVisible
, spec, body)
99 Dlet
(ident
"f",false,Expr.RKnone
, expr
f)
101 (ident
"M2",[use_int_Int ; f])
110 ensures { result >= 0 }
111 = let x = ref 42 in !x
117 let ge_int = qualid
["Int";Ident.op_infix
">="]
121 let use_int_Int = use ~import
:false (["int";"Int"]) in
123 let use_ref_Ref = use ~import
:false (["ref";"Ref"]) in
126 let result = ident
"result" in
127 let post = term
(Tidapp
(ge_int,[tvar
(Qident
result);tconst
0])) in
130 sp_post
= [Loc.dummy_position
,[pat_var
result,post]];
142 let e1 = eapply
(evar
(qualid
["Ref";"ref"])) (econst
42) in
143 let id_x = ident
"x" in
144 let qid = qualid
["Ref";Ident.op_prefix
"!"] in
145 let e2 = eapply
(evar
qid) (evar
(Qident
id_x)) in
146 expr
(Elet
(id_x,false,Expr.RKnone
,e1,e2))
148 let f = Efun
(unit_binder
(),None
,pat Pwild
,Ity.MaskVisible
,spec,body)
150 Dlet
(ident
"f",false,Expr.RKnone
, expr
f)
152 (ident
"M3",[use_int_Int ; use_ref_Ref ; f])
158 let f (a:array int) : unit
159 requires { a.length >= 1 }
160 ensures { a[0] = 42 }
168 let array_int_type = PTtyapp
(qualid
["Array";"array"],[int_type])
170 let length = qualid
["Array";"length"]
172 let array_get = qualid
["Array"; Ident.op_get
""]
174 let array_set = qualid
["Array"; Ident.op_set
""]
178 let use_int_Int = use ~import
:false (["int";"Int"]) in
179 (* use array.Array *)
180 let use_array_Array = use ~import
:false (["array";"Array"]) in
183 let id_a = ident
"a" in
185 tapp
ge_int [tapp
length [tvar
(Qident
id_a)]; tconst
1]
188 tapp
eq_symb [tapp
array_get [tvar
(Qident
id_a); tconst
0];
193 sp_post
= [Loc.dummy_position
,[pat Pwild
,post]];
205 eapp
array_set [evar
(Qident
id_a); econst
0; econst
42]
207 let f = Efun
(one_binder ~pty
:array_int_type "a",
208 None
,pat Pwild
,Ity.MaskVisible
,spec,body)
210 Dlet
(ident
"f", false, Expr.RKnone
, expr
f)
212 (ident
"M4",[use_int_Int ; use_array_Array ; f])
215 (* The following example is not in the manual
216 * it shows how to use Ptree API for scope/import declarations
219 function f (x : int) : int = x
229 let use_int_Int = use ~import
:false (["int";"Int"]) in
235 ld_loc
= Loc.dummy_position
;
236 ld_ident
= ident
"f";
237 ld_params
= [(Loc.dummy_position
,Some
(ident
"x"),false,int_type)] ;
238 ld_type
= Some
int_type;
239 ld_def
= Some
(tvar
(Qident
(ident
"x"))) ;
243 Dscope
(Loc.dummy_position
,false,ident
"S",[f])
246 let import_S = Dimport
(qualid
["S"]) in
247 (* goal g : f 2 = 2 *)
249 let two = tconst
2 in
250 let eq_int = qualid
["Int";Ident.op_infix
"="] in
251 let f_of_two = tapp
(qualid
["f"]) [two] in
252 let goal_term = tapp
eq_int [f_of_two ; two] in
253 Dprop
(Decl.Pgoal
,ident
"g",goal_term)
255 (ident
"M45",[use_int_Int ; scope_S ; import_S ; g])
257 (* BEGIN{getmodules} *)
258 let mlw_file = Modules
[mod_M1 ; mod_M2 ; mod_M3 ; mod_M4]
259 (* END{getmodules} *)
263 let () = printf
"%a@." (Mlw_printer.pp_mlw_file ~attr
:true) mlw_file
265 (* BEGIN{topdownf} *)
267 let uc = F.create
() in
268 let uc = F.begin_module
uc "M5" in
269 let uc = F.use
uc ~import
:false ["int";"Int"] in
270 let uc = F.use
uc ~import
:false ["array";"Array"] in
271 let uc = F.begin_let
uc "f" (one_binder ~pty
:array_int_type "a") in
272 let id_a = Qident
(ident
"a") in
273 let pre = tapp
ge_int [tapp
length [tvar
id_a]; tconst
1] in
274 let uc = F.add_pre
uc pre in
276 tapp
eq_symb [tapp
array_get [tvar
id_a; tconst
0];
279 let uc = F.add_post
uc post in
280 let body = eapp
array_set [evar
id_a; econst
0; econst
42] in
281 let uc = F.add_body
uc body in
282 let uc = F.end_module
uc in
286 let () = printf
"%a@." (Mlw_printer.pp_mlw_file ~attr
:true) mlw_file
288 (* BEGIN{topdowni} *)
291 I.use ~import
:false ["int";"Int"];
292 I.use ~import
:false ["array";"Array"];
293 I.begin_let
"f" (one_binder ~pty
:array_int_type "a");
294 let id_a = Qident
(ident
"a") in
295 let pre = tapp
ge_int [tapp
length [tvar
id_a]; tconst
1] in
298 tapp
eq_symb [tapp
array_get [tvar
id_a; tconst
0];
302 let body = eapp
array_set [evar
id_a; econst
0; econst
42] in
309 (* Printing back the mlw file *)
311 (* BEGIN{mlwprinter} *)
312 let () = printf
"%a@." (Mlw_printer.pp_mlw_file ~attr
:true) mlw_file
313 (* END{mlwprinter} *)
315 (* BEGIN{typemodules} *)
316 let mods = Typing.type_mlw_file
env [] "myfile.mlw" mlw_file
317 (* END{typemodules} *)
319 (* BEGIN{typemoduleserror} *)
322 Typing.type_mlw_file
env [] "myfile.mlw" mlw_file
323 with Loc.Located
(loc
, e
) -> (* A located exception [e] *)
324 let msg = asprintf
"%a" Exn_printer.exn_printer e
in
326 (Mlw_printer.with_marker ~
msg loc
(Mlw_printer.pp_mlw_file ~attr
:true))
329 (* END{typemoduleserror} *)
331 (* Checking the VCs *)
333 (* BEGIN{checkingvcs} *)
334 let my_tasks : Task.task list
=
339 (Task.split_theory m
.Pmodule.mod_theory None None
) acc
)
345 let provers : Whyconf.config_prover
Whyconf.Mprover.t
=
346 Whyconf.get_provers
config
348 (* default resource limits *)
350 Call_provers.{empty_limits
with
351 limit_time
= Whyconf.timelimit
main;
352 limit_mem
= Whyconf.memlimit
main }
354 let alt_ergo : Whyconf.config_prover
=
355 let fp = Whyconf.parse_filter_prover
"Alt-Ergo" in
356 let provers = Whyconf.filter_provers
config fp in
357 if Whyconf.Mprover.is_empty
provers then begin
358 eprintf
"Prover Alt-Ergo not installed or not configured@.";
361 snd
(Whyconf.Mprover.max_binding
provers)
363 let alt_ergo_driver : Driver.driver
=
365 Driver.load_driver_for_prover
main env alt_ergo
367 eprintf
"Failed to load driver for alt-ergo: %a@."
368 Exn_printer.exn_printer e
;
372 List.iteri
(fun i t
->
374 Driver.prove_task ~
limits ~
config:main
375 ~command
:alt_ergo.Whyconf.command
alt_ergo_driver t
in
376 let r = Call_provers.wait_on_call
call in
377 printf
"@[On task %d, alt-ergo answers %a@." (succ i
)
378 (Call_provers.print_prover_result ?json
:None
) r)
380 (* END{checkingvcs} *)
384 compile-command: "make -C ../.. test-api-mlw_tree"