do not take resource limits from more than one source
[why3.git] / examples / use_api / mlw_tree.ml
blob11d48b9ae3a5313b9b650732e1b2e085be0b8e59
1 (********************************************************************)
2 (* *)
3 (* The Why3 Verification Platform / The Why3 Development Team *)
4 (* Copyright 2010-2023 -- Inria - CNRS - Paris-Saclay University *)
5 (* *)
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. *)
9 (* *)
10 (********************************************************************)
12 (*******************
14 This file builds some MLW modules, using parse trees instead of direct
15 API calls
17 ******************)
19 (* BEGIN{buildenv} *)
20 open Why3
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)
24 open Ptree
25 open Ptree_helpers
26 (* END{buildenv} *)
28 (* declaration of
29 BEGIN{source1}
30 module M1
31 use int.Int
32 goal g : 2 + 2 = 4
33 end
34 END{source1}
37 (* BEGIN{code1} *)
38 let mod_M1 =
39 (* use int.Int *)
40 let use_int_Int = use ~import:false (["int";"Int"]) in
41 (* goal g : 2 + 2 = 4 *)
42 let g =
43 let two = tconst 2 in
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])
52 (* END{code1} *)
55 (* declaration of
56 BEGIN{source2}
57 module M2
58 let f (x:int) : int
59 requires { x=6 }
60 ensures { result=42 }
61 = x*7
62 end
63 END{source2}
66 (* BEGIN{code2} *)
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 "*"]
72 let mod_M2 =
73 (* use int.Int *)
74 let use_int_Int = use ~import:false (["int";"Int"]) in
75 (* f *)
76 let f =
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
81 let spec = {
82 sp_pre = [pre];
83 sp_post = [Loc.dummy_position,[pat_var result,post]];
84 sp_xpost = [];
85 sp_reads = [];
86 sp_writes = [];
87 sp_alias = [];
88 sp_variant = [];
89 sp_checkrw = false;
90 sp_diverge = false;
91 sp_partial = false;
94 let body = eapp mul_int [evar (Qident id_x); econst 7] in
95 let f =
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])
102 (* END{code2} *)
105 (* declaration of
106 BEGIN{source3}
107 module M3
108 let f() : int
109 requires { true }
110 ensures { result >= 0 }
111 = let x = ref 42 in !x
113 END{source3}
116 (* BEGIN{code3} *)
117 let ge_int = qualid ["Int";Ident.op_infix ">="]
119 let mod_M3 =
120 (* use int.Int *)
121 let use_int_Int = use ~import:false (["int";"Int"]) in
122 (* use ref.Ref *)
123 let use_ref_Ref = use ~import:false (["ref";"Ref"]) in
124 (* f *)
125 let f =
126 let result = ident "result" in
127 let post = term(Tidapp(ge_int,[tvar (Qident result);tconst 0])) in
128 let spec = {
129 sp_pre = [];
130 sp_post = [Loc.dummy_position,[pat_var result,post]];
131 sp_xpost = [];
132 sp_reads = [];
133 sp_writes = [];
134 sp_alias = [];
135 sp_variant = [];
136 sp_checkrw = false;
137 sp_diverge = false;
138 sp_partial = false;
141 let body =
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])
153 (* END{code3} *)
155 (* declaration of
156 BEGIN{source4}
157 module M4
158 let f (a:array int) : unit
159 requires { a.length >= 1 }
160 ensures { a[0] = 42 }
161 = a[0] <- 42
163 END{source4}
166 (* BEGIN{code4} *)
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 ""]
176 let mod_M4 =
177 (* use int.Int *)
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
181 (* use f *)
182 let f =
183 let id_a = ident "a" in
184 let pre =
185 tapp ge_int [tapp length [tvar (Qident id_a)]; tconst 1]
187 let post =
188 tapp eq_symb [tapp array_get [tvar (Qident id_a); tconst 0];
189 tconst 42]
191 let spec = {
192 sp_pre = [pre];
193 sp_post = [Loc.dummy_position,[pat Pwild,post]];
194 sp_xpost = [];
195 sp_reads = [];
196 sp_writes = [];
197 sp_alias = [];
198 sp_variant = [];
199 sp_checkrw = false;
200 sp_diverge = false;
201 sp_partial = false;
204 let body =
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])
213 (* END{code4} *)
215 (* The following example is not in the manual
216 * it shows how to use Ptree API for scope/import declarations
217 module M5
218 scope S
219 function f (x : int) : int = x
222 import S
223 goal g : f 2 = 2
227 let mod_M45 =
228 (* use int.Int *)
229 let use_int_Int = use ~import:false (["int";"Int"]) in
230 (* scope S *)
231 let scope_S =
232 (* f *)
233 let f =
234 let logic = {
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"))) ;
240 } in
241 Dlogic([logic])
243 Dscope(Loc.dummy_position,false,ident "S",[f])
245 (* import S *)
246 let import_S = Dimport (qualid ["S"]) in
247 (* goal g : f 2 = 2 *)
248 let g =
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} *)
261 open Format
263 let () = printf "%a@." (Mlw_printer.pp_mlw_file ~attr:true) mlw_file
265 (* BEGIN{topdownf} *)
266 let mlw_file =
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
275 let post =
276 tapp eq_symb [tapp array_get [tvar id_a; tconst 0];
277 tconst 42]
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
283 F.get_mlw_file uc
284 (* END{topdownf} *)
286 let () = printf "%a@." (Mlw_printer.pp_mlw_file ~attr:true) mlw_file
288 (* BEGIN{topdowni} *)
289 let mlw_file =
290 I.begin_module "M6";
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
296 I.add_pre pre;
297 let post =
298 tapp eq_symb [tapp array_get [tvar id_a; tconst 0];
299 tconst 42]
301 I.add_post post;
302 let body = eapp array_set [evar id_a; econst 0; econst 42] in
303 I.add_body body;
304 I.end_module ();
305 I.get_mlw_file ()
306 (* END{topdowni} *)
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} *)
320 let _mods =
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
325 printf "%a@."
326 (Mlw_printer.with_marker ~msg loc (Mlw_printer.pp_mlw_file ~attr:true))
327 mlw_file;
328 exit 1
329 (* END{typemoduleserror} *)
331 (* Checking the VCs *)
333 (* BEGIN{checkingvcs} *)
334 let my_tasks : Task.task list =
335 let mods =
336 Wstdlib.Mstr.fold
337 (fun _ m acc ->
338 List.rev_append
339 (Task.split_theory m.Pmodule.mod_theory None None) acc)
340 mods []
341 in List.rev mods
345 let provers : Whyconf.config_prover Whyconf.Mprover.t =
346 Whyconf.get_provers config
348 (* default resource limits *)
349 let 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@.";
359 exit 1
360 end else
361 snd (Whyconf.Mprover.max_binding provers)
363 let alt_ergo_driver : Driver.driver =
365 Driver.load_driver_for_prover main env alt_ergo
366 with e ->
367 eprintf "Failed to load driver for alt-ergo: %a@."
368 Exn_printer.exn_printer e;
369 exit 1
371 let () =
372 List.iteri (fun i t ->
373 let call =
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)
379 my_tasks
380 (* END{checkingvcs} *)
383 Local Variables:
384 compile-command: "make -C ../.. test-api-mlw_tree"
385 End: