diff --git a/src/plugins/wp/ProverWhy3.ml b/src/plugins/wp/ProverWhy3.ml index d0d05905e1eccea824ddad15a7e1efc1bad52977..f225a3cb684399e3b2bbab5eee7cc9b7534047bd 100644 --- a/src/plugins/wp/ProverWhy3.ml +++ b/src/plugins/wp/ProverWhy3.ml @@ -68,6 +68,8 @@ type convert = { pool: Lang.F.pool; polarity: Cvalues.polarity; in_goal: bool; + incomplete_types: (string, Why3.Ty.tysymbol) Hashtbl.t; + incomplete_symbols: (string, Why3.Term.lsymbol) Hashtbl.t; mutable convert_for_export: Lang.F.term Lang.F.Tmap.t; } @@ -163,6 +165,8 @@ let empty_cnv ?(polarity=`NoPolarity) ?(in_goal=false) (ctx:context) : convert = env = ctx.env; polarity; in_goal; + incomplete_symbols = Hashtbl.create 3; + incomplete_types = Hashtbl.create 3; convert_for_export = Lang.F.Tmap.empty; } @@ -252,7 +256,12 @@ let rec of_tau ~cnv (t:Lang.F.tau) = Some (Why3.Ty.ty_app ts [Why3.Opt.get (of_tau ~cnv k); Why3.Opt.get (of_tau ~cnv v)]) | Data(adt,l) -> begin let s = name_of_adt adt in - match Why3.Theory.(ns_find_ts (get_namespace cnv.th) (cut_path s)) with + let find s = + try Hashtbl.find cnv.incomplete_types s + with Not_found -> + Why3.Theory.(ns_find_ts (get_namespace cnv.th) (cut_path s)) + in + match find s with | ts -> Some (Why3.Ty.ty_app ts (List.map (fun e -> Why3.Opt.get (of_tau ~cnv e)) l)) | exception Not_found -> why3_failure "Can't find type '%s' in why3 namespace" s @@ -457,7 +466,12 @@ let rec of_term ~cnv expected t : Why3.Term.term = Why3.Term.t_app ls l r in let apply_from_ns s l sort = - match Why3.Theory.(ns_find_ls (get_namespace cnv.th) (cut_path s)), expected with + let find s = + try Hashtbl.find cnv.incomplete_symbols s + with Not_found -> + Why3.Theory.(ns_find_ls (get_namespace cnv.th) (cut_path s)) + in + match find s, expected with | ls, (Prop | Bool) -> coerce ~cnv sort expected $ t_app ls l (of_tau cnv sort) @@ -670,7 +684,7 @@ class visitor (ctx:context) c = v#add_builtin_lib; v#vself; let th = Why3.Theory.close_theory ctx.th in - if Wp_parameters.has_dkey ProverErgo.dkey_cluster then + if Wp_parameters.has_print_generated () then Log.print_on_output begin fun fmt -> Format.fprintf fmt "---------------------------------------------@\n" ; @@ -784,13 +798,15 @@ class visitor (ctx:context) c = let decl = Why3.Decl.create_ty_decl id in ctx.th <- Why3.Theory.add_decl ~warn:false ctx.th decl; | Tsum cases -> - let id = Why3.Ident.id_fresh (Lang.type_id lt) in + let name = Lang.type_id lt in + let id = Why3.Ident.id_fresh name in let map i _ = tvar i in let tv_args = List.mapi map lt.lt_params in let tys = Why3.Ty.create_tysymbol id tv_args NoDef in + let cnv = empty_cnv ctx in + Hashtbl.add cnv.incomplete_types name tys ; let tv_args = List.map Why3.Ty.ty_var tv_args in let return_ty = Why3.Ty.ty_app tys tv_args in - let cnv = empty_cnv ctx in let constr = List.length cases in let cases = List.map (fun (c,targs) -> let name = match c with | Lang.CTOR c -> Lang.ctor_id c | _ -> assert false in @@ -803,13 +819,15 @@ class visitor (ctx:context) c = let decl = Why3.Decl.create_data_decl [tys,cases] in ctx.th <- Why3.Theory.add_decl ~warn:false ctx.th decl; | Trec fields -> - let id = Why3.Ident.id_fresh (Lang.type_id lt) in + let name = Lang.type_id lt in + let id = Why3.Ident.id_fresh name in let map i _ = tvar i in let tv_args = List.mapi map lt.lt_params in let tys = Why3.Ty.create_tysymbol id tv_args NoDef in + let cnv = empty_cnv ctx in + Hashtbl.add cnv.incomplete_types name tys ; let tv_args = List.map Why3.Ty.ty_var tv_args in let return_ty = Why3.Ty.ty_app tys tv_args in - let cnv = empty_cnv ctx in let fields,args = List.split @@ List.map (fun (f,ty) -> let name = Lang.name_of_field f in let id = Why3.Ident.id_fresh name in @@ -847,21 +865,23 @@ class visitor (ctx:context) c = ctx.th <- Why3.Theory.add_decl ~warn:false ctx.th decl; end + method private make_lemma cnv (l: Definitions.dlemma) = + let id = Why3.Ident.id_fresh (Lang.lemma_id l.l_name) in + let id = Why3.Decl.create_prsymbol id in + List.iter (Lang.F.add_var cnv.pool) l.l_forall; + let cnv, vars = Lang.For_export.in_state (mk_binders cnv) l.l_forall in + let t = convert cnv Prop (Lang.F.e_prop l.l_lemma) in + let triggers = full_triggers l.l_triggers in + let triggers = Lang.For_export.in_state (List.map (List.map (of_trigger ~cnv))) triggers in + let t = Why3.Term.t_forall_close vars triggers t in + id, t + method on_dlemma l = - begin - let kind = Why3.Decl.(if l.l_assumed then Paxiom else Plemma) in - let id = Why3.Ident.id_fresh (Lang.lemma_id l.l_name) in - let id = Why3.Decl.create_prsymbol id in - let cnv = empty_cnv ctx in - List.iter (Lang.F.add_var cnv.pool) l.l_forall; - let cnv, vars = Lang.For_export.in_state (mk_binders cnv) l.l_forall in - let t = convert cnv Prop (Lang.F.e_prop l.l_lemma) in - let triggers = full_triggers l.l_triggers in - let triggers = Lang.For_export.in_state (List.map (List.map (of_trigger ~cnv))) triggers in - let t = Why3.Term.t_forall_close vars triggers t in - let decl = Why3.Decl.create_prop_decl kind id t in - ctx.th <- Why3.Theory.add_decl ~warn:false ctx.th decl; - end + let kind = Why3.Decl.(if l.l_assumed then Paxiom else Plemma) in + let cnv = empty_cnv ctx in + let id, t = self#make_lemma cnv l in + let decl = Why3.Decl.create_prop_decl kind id t in + ctx.th <- Why3.Theory.add_decl ~warn:false ctx.th decl method on_dfun d = Wp_parameters.debug ~dkey:dkey_api "Define %a@." Lang.Fun.pretty d.d_lfun ; @@ -952,14 +972,18 @@ class visitor (ctx:context) c = end | Inductive dl -> (* create predicate symbol *) - let id = Why3.Ident.id_fresh (Qed.Export.link_name (lfun_name d.d_lfun)) in + let fname = Qed.Export.link_name (lfun_name d.d_lfun) in + let id = Why3.Ident.id_fresh fname in let map e = Why3.Opt.get (of_tau ~cnv (Lang.F.tau_of_var e)) in let ty_args = List.map map d.d_params in - let id = Why3.Term.create_lsymbol id ty_args None in - let decl = Why3.Decl.create_param_decl id in - ctx.th <- Why3.Theory.add_decl ~warn:false ctx.th decl ; - (* register axioms *) - List.iter (self#on_dlemma) dl + let fid = Why3.Term.create_lsymbol id ty_args None in + let make_case (l:Definitions.dlemma) = + let cnv = empty_cnv ctx in + Hashtbl.add cnv.incomplete_symbols fname fid ; + self#make_lemma cnv l + in + let ind_decl = (fid, List.map make_case dl) in + ctx.th <- Why3.Theory.add_ind_decl ctx.th Why3.Decl.Ind [ind_decl] end end diff --git a/src/plugins/wp/tests/wp/oracle/sharing.res.oracle b/src/plugins/wp/tests/wp/oracle/sharing.res.oracle index d0bde7870b7a8cade014142226f5f026c223bd3b..ea52c7dcb27540192bf438772975bf952af017e5 100644 --- a/src/plugins/wp/tests/wp/oracle/sharing.res.oracle +++ b/src/plugins/wp/tests/wp/oracle/sharing.res.oracle @@ -4,6 +4,28 @@ [wp] Loading driver 'share/wp.driver' [wp] Warning: Missing RTE guards [wp] 1 goal scheduled +--------------------------------------------- +--- Context 'typed_f' Cluster 'Compound' +--------------------------------------------- +theory Compound + (* use why3.BuiltIn.BuiltIn *) + + (* use bool.Bool *) + + (* use int.Int *) + + (* use int.ComputerDivision *) + + (* use real.RealInfix *) + + (* use frama_c_wp.qed.Qed *) + + (* use map.Map *) + + (* use frama_c_wp.memory.Memory *) + + function shift_sint32 (p:addr) (k:int) : addr = shift p k +end [wp:print-generated] theory WP (* use why3.BuiltIn.BuiltIn *) diff --git a/src/plugins/wp/tests/wp_acsl/oracle/inductive.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle/inductive.res.oracle index d8cb3e9a8d05e830be50775f2197d99d3aaa12af..a1016679f96bf1124f0d163eec275e1e005514b5 100644 --- a/src/plugins/wp/tests/wp_acsl/oracle/inductive.res.oracle +++ b/src/plugins/wp/tests/wp_acsl/oracle/inductive.res.oracle @@ -3,6 +3,30 @@ [wp] Running WP plugin... [wp] Loading driver 'share/wp.driver' [wp] 3 goals scheduled +--------------------------------------------- +--- Context 'typed' Cluster 'Compound' +--------------------------------------------- +theory Compound + (* use why3.BuiltIn.BuiltIn *) + + (* use bool.Bool *) + + (* use int.Int *) + + (* use int.ComputerDivision *) + + (* use real.RealInfix *) + + (* use frama_c_wp.qed.Qed *) + + (* use map.Map *) + + (* use frama_c_wp.memory.Memory *) + + function shift_sint32 (p:addr) (k:int) : addr = shift p k + + function shiftfield_F1__list_next (p:addr) : addr = shift p 1 +end [wp:print-generated] theory WP (* use why3.BuiltIn.BuiltIn *) @@ -19,12 +43,10 @@ (* use map.Map *) - predicate P_is_gcd int int int - - axiom Q_gcd_zero : forall n:int. P_is_gcd n 0 n - - axiom Q_gcd_succ : - forall a:int, b:int, d:int. P_is_gcd b (mod a b) d -> P_is_gcd a b d + inductive P_is_gcd int int int = + | Q_gcd_zero : forall n:int. P_is_gcd n 0 n + | Q_gcd_succ : + forall a:int, b:int, d:int. P_is_gcd b (mod a b) d -> P_is_gcd a b d lemma Q_test_no_label : forall a:int, b:int, d:int. P_is_gcd a b d -> not P_is_gcd b d a @@ -33,17 +55,15 @@ (* use Compound *) - predicate P_reachable (int -> int) (addr -> addr) addr addr - - axiom Q_root_reachable : - forall malloc:int -> int, mptr:addr -> addr, root:addr. - P_reachable malloc mptr root root - - axiom Q_next_reachable : - forall malloc:int -> int, mptr:addr -> addr, root:addr, node:addr. - valid_rw malloc root 2 -> - P_reachable malloc mptr (get mptr (shiftfield_F1__list_next root)) node -> - P_reachable malloc mptr root node + inductive P_reachable (int -> int) (addr -> addr) addr addr = + | Q_root_reachable : + forall malloc:int -> int, mptr:addr -> addr, root:addr. + P_reachable malloc mptr root root + | Q_next_reachable : + forall malloc:int -> int, mptr:addr -> addr, root:addr, node:addr. + valid_rw malloc root 2 -> + P_reachable malloc mptr (get mptr (shiftfield_F1__list_next root)) + node -> P_reachable malloc mptr root node goal wp_goal : forall t:int -> int, t1:addr -> addr, t2:int -> int, t3:addr -> addr, a: @@ -65,12 +85,11 @@ (* use map.Map *) - predicate P_is_gcd1 int int int - - axiom Q_gcd_zero1 : forall n:int. P_is_gcd1 n 0 n - - axiom Q_gcd_succ1 : - forall a:int, b:int, d:int. P_is_gcd1 b (mod a b) d -> P_is_gcd1 a b d + inductive P_is_gcd1 int int int = + | Q_gcd_zero1 : forall n:int. P_is_gcd1 n 0 n + | Q_gcd_succ1 : + forall a:int, b:int, d:int. + P_is_gcd1 b (mod a b) d -> P_is_gcd1 a b d goal wp_goal : forall i:int, i1:int, i2:int. P_is_gcd1 i i1 i2 -> not P_is_gcd1 i1 i2 i @@ -95,29 +114,26 @@ (* use Compound *) - predicate P_reachable1 (int -> int) (addr -> addr) addr addr - - axiom Q_root_reachable1 : - forall malloc:int -> int, mptr:addr -> addr, root:addr. - P_reachable1 malloc mptr root root - - axiom Q_next_reachable1 : - forall malloc:int -> int, mptr:addr -> addr, root:addr, node:addr. - valid_rw malloc root 2 -> - P_reachable1 malloc mptr (get mptr (shiftfield_F1__list_next root)) node -> - P_reachable1 malloc mptr root node + inductive P_reachable1 (int -> int) (addr -> addr) addr addr = + | Q_root_reachable1 : + forall malloc:int -> int, mptr:addr -> addr, root:addr. + P_reachable1 malloc mptr root root + | Q_next_reachable1 : + forall malloc:int -> int, mptr:addr -> addr, root:addr, node:addr. + valid_rw malloc root 2 -> + P_reachable1 malloc mptr (get mptr (shiftfield_F1__list_next root)) + node -> P_reachable1 malloc mptr root node lemma Q_test_one_label : forall malloc:int -> int, mptr:addr -> addr, malloc1:int -> int, mptr1: addr -> addr, l1:addr, l2:addr. P_reachable1 malloc1 mptr1 l1 l2 -> not P_reachable1 malloc mptr l1 l2 - predicate P_is_gcd2 int int int - - axiom Q_gcd_zero2 : forall n:int. P_is_gcd2 n 0 n - - axiom Q_gcd_succ2 : - forall a:int, b:int, d:int. P_is_gcd2 b (mod a b) d -> P_is_gcd2 a b d + inductive P_is_gcd2 int int int = + | Q_gcd_zero2 : forall n:int. P_is_gcd2 n 0 n + | Q_gcd_succ2 : + forall a:int, b:int, d:int. + P_is_gcd2 b (mod a b) d -> P_is_gcd2 a b d lemma Q_test_no_label1 : forall a:int, b:int, d:int. P_is_gcd2 a b d -> not P_is_gcd2 b d a @@ -142,26 +158,23 @@ i1 < end1 -> get mint1 (shift_sint32 a i1) = get mint (shift_sint32 b i1)) - predicate P_same_elements (addr -> int) (addr -> int) addr addr int int - - axiom Q_refl : - forall mint:addr -> int, mint1:addr -> int, a:addr, b:addr, begin:int, - end1:int. - P_same_array mint mint1 a b begin end1 -> - P_same_elements mint mint1 a b begin end1 - - axiom Q_swap : - forall mint:addr -> int, mint1:addr -> int, a:addr, b:addr, begin:int, i: - int, j:int, end1:int. - P_swap mint mint1 a b begin i j end1 -> - P_same_elements mint mint1 a b begin end1 - - axiom Q_trans : - forall mint:addr -> int, mint1:addr -> int, mint2:addr -> int, a:addr, b: - addr, c:addr, begin:int, end1:int. - P_same_elements mint mint1 b c begin end1 -> - P_same_elements mint1 mint2 a b begin end1 -> - P_same_elements mint mint2 a c begin end1 + inductive P_same_elements (addr -> int) (addr -> int) addr addr int int = + | Q_refl : + forall mint:addr -> int, mint1:addr -> int, a:addr, b:addr, begin: + int, end1:int. + P_same_array mint mint1 a b begin end1 -> + P_same_elements mint mint1 a b begin end1 + | Q_swap : + forall mint:addr -> int, mint1:addr -> int, a:addr, b:addr, begin: + int, i:int, j:int, end1:int. + P_swap mint mint1 a b begin i j end1 -> + P_same_elements mint mint1 a b begin end1 + | Q_trans : + forall mint:addr -> int, mint1:addr -> int, mint2:addr -> int, a: + addr, b:addr, c:addr, begin:int, end1:int. + P_same_elements mint mint1 b c begin end1 -> + P_same_elements mint1 mint2 a b begin end1 -> + P_same_elements mint mint2 a c begin end1 goal wp_goal : forall t:addr -> int, t1:addr -> int, t2:addr -> int, a:addr, a1:addr, i: diff --git a/src/plugins/wp/tests/wp_typed/oracle/struct_array_type.res.oracle b/src/plugins/wp/tests/wp_typed/oracle/struct_array_type.res.oracle index fb6e3336de647eebe03fb9c24e275611ec4c23d9..82901ded836c14ba3f2ba30ec3e14fc6463f440b 100644 --- a/src/plugins/wp/tests/wp_typed/oracle/struct_array_type.res.oracle +++ b/src/plugins/wp/tests/wp_typed/oracle/struct_array_type.res.oracle @@ -4,6 +4,27 @@ [wp] Loading driver 'share/wp.driver' [wp] Warning: Missing RTE guards [wp] 1 goal scheduled +--------------------------------------------- +--- Context 'typed_f' Cluster 'S1_s' +--------------------------------------------- +theory S1_s + (* use why3.BuiltIn.BuiltIn *) + + (* use bool.Bool *) + + (* use int.Int *) + + (* use int.ComputerDivision *) + + (* use real.RealInfix *) + + (* use frama_c_wp.qed.Qed *) + + (* use map.Map *) + + type S1_s = + | S1_s1 (F1_s_a:int -> int) (F1_s_b:int -> int) +end [wp:print-generated] theory WP (* use why3.BuiltIn.BuiltIn *)