1 (********************************************************************)
3 (* The Why3 Verification Platform / The Why3 Development Team *)
4 (* Copyright 2010-2024 -- 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 }
161 ensures { a[0] = 42 }
169 let array_int_type = PTtyapp
(qualid
["Array";"array"],[int_type])
171 let length = qualid
["Array";"length"]
173 let array_get = qualid
["Array"; Ident.op_get
""]
175 let array_set = qualid
["Array"; Ident.op_set
""]
179 let use_int_Int = use ~import
:false (["int";"Int"]) in
180 (* use array.Array *)
181 let use_array_Array = use ~import
:false (["array";"Array"]) in
184 let id_a = ident
"a" in
186 tapp
ge_int [tapp
length [tvar
(Qident
id_a)]; tconst
1]
189 tapp
eq_symb [tapp
array_get [tvar
(Qident
id_a); tconst
0];
194 sp_post
= [Loc.dummy_position
,[pat Pwild
,post]];
197 sp_writes
= [tvar
(Qident
id_a)];
206 eapp
array_set [evar
(Qident
id_a); econst
0; econst
42]
208 let f = Efun
(one_binder ~pty
:array_int_type "a",
209 None
,pat Pwild
,Ity.MaskVisible
,spec,body)
211 Dlet
(ident
"f", false, Expr.RKnone
, expr
f)
213 (ident
"M4",[use_int_Int ; use_array_Array ; f])
216 (* The following example is not in the manual
217 * it shows how to use Ptree API for global variable declaration
221 let f () : unit = x <- x+1
227 let use_int_Int = use ~import
:false (["int";"Int"]) in
229 let id_x,decl_x
= global_var_decl
int_type "x" in
237 sp_writes
= [tvar
(Qident
id_x)];
245 let add_int = qualid
["Int";Ident.op_infix
"+"] in
246 let xp1 = eapp
add_int [evar
(Qident
id_x) ; econst
1 ] in
247 let body = expr
(Eassign
[ expr
(Easref
(Qident
id_x)), None
, xp1 ]) in
248 let f = Efun
(unit_binder
(),None
,pat Pwild
,Ity.MaskVisible
,spec,body) in
249 Dlet
(ident
"f", false, Expr.RKnone
, expr
f)
252 (ident
"Mglob",[use_int_Int ; decl_x
; decl_f])
254 (* The following example is not in the manual
255 * it shows how to use Ptree API for scope/import declarations
258 function f (x : int) : int = x
268 let use_int_Int = use ~import
:false (["int";"Int"]) in
274 ld_loc
= Loc.dummy_position
;
275 ld_ident
= ident
"f";
276 ld_params
= [(Loc.dummy_position
,Some
(ident
"x"),false,int_type)] ;
277 ld_type
= Some
int_type;
278 ld_def
= Some
(tvar
(Qident
(ident
"x"))) ;
282 Dscope
(Loc.dummy_position
,false,ident
"S",[f])
285 let import_S = Dimport
(qualid
["S"]) in
286 (* goal g : f 2 = 2 *)
288 let two = tconst
2 in
289 let eq_int = qualid
["Int";Ident.op_infix
"="] in
290 let f_of_two = tapp
(qualid
["f"]) [two] in
291 let goal_term = tapp
eq_int [f_of_two ; two] in
292 Dprop
(Decl.Pgoal
,ident
"g",goal_term)
294 (ident
"Mscope",[use_int_Int ; scope_S ; import_S ; g])
296 (* BEGIN{getmodules} *)
297 let mlw_file = Modules
[mod_M1 ; mod_M2 ; mod_M3 ; mod_M4]
298 (* END{getmodules} *)
299 let mlw_file_others = Modules
[mod_Mglob ; mod_Mscope]
303 (* Printing back the mlw file *)
304 (* BEGIN{mlwprinter} *)
305 let () = printf
"%a@." (Mlw_printer.pp_mlw_file ~attr
:true) mlw_file
306 (* END{mlwprinter} *)
308 let () = printf
"%a@." (Mlw_printer.pp_mlw_file ~attr
:true) mlw_file_others
310 (* BEGIN{topdownf} *)
312 let uc = F.create
() in
313 let uc = F.begin_module
uc "M5" in
314 let uc = F.use
uc ~import
:false ["int";"Int"] in
315 let uc = F.use
uc ~import
:false ["array";"Array"] in
316 let uc = F.begin_let
uc "f" (one_binder ~pty
:array_int_type "a") in
317 let id_a = Qident
(ident
"a") in
318 let pre = tapp
ge_int [tapp
length [tvar
id_a]; tconst
1] in
319 let uc = F.add_pre
uc pre in
320 let uc = F.add_writes
uc [tvar
id_a] in
322 tapp
eq_symb [tapp
array_get [tvar
id_a; tconst
0];
325 let uc = F.add_post
uc post in
326 let body = eapp
array_set [evar
id_a; econst
0; econst
42] in
327 let uc = F.add_body
uc body in
328 let uc = F.end_module
uc in
332 let () = printf
"%a@." (Mlw_printer.pp_mlw_file ~attr
:true) mlw_file_F
334 (* BEGIN{topdowni} *)
337 I.use ~import
:false ["int";"Int"];
338 I.use ~import
:false ["array";"Array"];
339 I.begin_let
"f" (one_binder ~pty
:array_int_type "a");
340 let id_a = Qident
(ident
"a") in
341 let pre = tapp
ge_int [tapp
length [tvar
id_a]; tconst
1] in
343 I.add_writes
[tvar
id_a];
345 tapp
eq_symb [tapp
array_get [tvar
id_a; tconst
0];
349 let body = eapp
array_set [evar
id_a; econst
0; econst
42] in
355 let () = printf
"%a@." (Mlw_printer.pp_mlw_file ~attr
:true) mlw_file_I
357 (* BEGIN{typemodules} *)
358 let mods = Typing.type_mlw_file
env [] "myfile.mlw" mlw_file
359 (* END{typemodules} *)
360 let mod_F = Typing.type_mlw_file
env [] "myFfile.mlw" mlw_file_F
361 let mod_I = Typing.type_mlw_file
env [] "myIfile.mlw" mlw_file_I
362 let mods_others = Typing.type_mlw_file
env [] "myotherfile.mlw" mlw_file_others
364 (* BEGIN{typemoduleserror} *)
367 Typing.type_mlw_file
env [] "myfile.mlw" mlw_file
368 with Loc.Located
(loc
, e
) -> (* A located exception [e] *)
369 let msg = asprintf
"%a" Exn_printer.exn_printer e
in
371 (Mlw_printer.with_marker ~
msg loc
(Mlw_printer.pp_mlw_file ~attr
:true))
374 (* END{typemoduleserror} *)
376 (* Checking the VCs *)
378 (* BEGIN{checkingvcs} *)
379 let my_tasks : Task.task list
=
384 (Task.split_theory m
.Pmodule.mod_theory None None
) acc
)
390 let provers : Whyconf.config_prover
Whyconf.Mprover.t
=
391 Whyconf.get_provers
config
393 (* default resource limits *)
395 Call_provers.{empty_limits
with
396 limit_time
= Whyconf.timelimit
main;
397 limit_mem
= Whyconf.memlimit
main }
399 let alt_ergo : Whyconf.config_prover
=
400 let fp = Whyconf.parse_filter_prover
"Alt-Ergo" in
401 let provers = Whyconf.filter_provers
config fp in
402 if Whyconf.Mprover.is_empty
provers then begin
403 eprintf
"Prover Alt-Ergo not installed or not configured@.";
406 snd
(Whyconf.Mprover.max_binding
provers)
408 let alt_ergo_driver : Driver.driver
=
410 Driver.load_driver_for_prover
main env alt_ergo
412 eprintf
"Failed to load driver for alt-ergo: %a@."
413 Exn_printer.exn_printer e
;
417 List.iteri
(fun i t
->
419 Driver.prove_task ~
limits ~
config:main
420 ~command
:alt_ergo.Whyconf.command
alt_ergo_driver t
in
421 let r = Call_provers.wait_on_call
call in
422 printf
"@[On task %d, alt-ergo answers %a@." (succ i
)
423 (Call_provers.print_prover_result ?json
:None
) r)
425 (* END{checkingvcs} *)
429 compile-command: "make -C ../.. test-api-mlw_tree"