Skip to content

Commit 63b8965

Browse files
strubGustavo2622
andcommitted
Improve rewrite framing with formula-level read tracking
It adds form/exnpost folding and formula read-analysis utilities, exposes statement-logic read extraction in ecLowPhlGoal, and updates ecPhlRewrite to build rewrite obligations from the actual framed precondition and written variables instead of relying on coarser statement-wide equality assumptions. Also increases test coverage for the proc change tactic. Co-Authored-By: Gustavo Delerue <gxdelerue@proton.me>
1 parent b6402f4 commit 63b8965

11 files changed

Lines changed: 526 additions & 72 deletions

File tree

src/ecAst.ml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -638,10 +638,14 @@ module POE = struct
638638
let to_list (poe : exnpost) =
639639
to_list_pre (destruct poe)
640640

641-
let iter (f : form -> unit) (poe : exnpost) =
642-
f poe.main;
643-
Mp.iter (fun _ -> f) (fst poe.exnmap);
644-
oiter f (snd poe.exnmap)
641+
let fold (tx : 'a -> form -> 'a) (state : 'a) (poe : exnpost) =
642+
let state = tx state poe.main in
643+
let state = Mp.fold (fun _ f state -> tx state f) (fst poe.exnmap) state in
644+
let state = ofold (fun f state -> tx state f) state (snd poe.exnmap) in
645+
state
646+
647+
let iter (tx : form -> unit) (poe : exnpost) =
648+
fold (fun () f -> tx f) () poe
645649

646650
let iter2 (f : form -> form -> unit) (poe1 : exnpost) (poe2 : exnpost) =
647651
let merge (a : form option) (b : form option) =

src/ecAst.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,8 @@ module POE : sig
401401

402402
val forall2 : (form -> form -> bool) -> exnpost -> exnpost -> bool
403403

404+
val fold : ('a -> form -> 'a) -> 'a -> exnpost -> 'a
405+
404406
val iter : (form -> unit) -> exnpost -> unit
405407

406408
val iter2 : (form -> form -> unit) -> exnpost -> exnpost -> unit

src/ecCoreFol.ml

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -535,33 +535,36 @@ let f_map gt g fp =
535535
f_pr_r { pr with pr_args = args'; pr_event = {m=pr.pr_event.m; inv=ev'}; }
536536

537537
(* -------------------------------------------------------------------- *)
538-
let f_iter g f =
538+
let f_fold (tx : 'a -> form -> 'a) (state : 'a) (f : form) =
539539
match f.f_node with
540540
| Fint _
541541
| Flocal _
542542
| Fpvar _
543543
| Fglob _
544-
| Fop _ -> ()
545-
546-
| Fquant (_ , _ , f1) -> g f1
547-
| Fif (f1, f2, f3) -> g f1;g f2; g f3
548-
| Fmatch (b, fs, _) -> List.iter g (b :: fs)
549-
| Flet (_, f1, f2) -> g f1;g f2
550-
| Fapp (e, es) -> List.iter g (e :: es)
551-
| Ftuple es -> List.iter g es
552-
| Fproj (e, _) -> g e
553-
554-
| FhoareF hf -> g (hf_pr hf).inv; POE.iter g (hf_po hf).hsi_inv
555-
| FhoareS hs -> g (hs_pr hs).inv; POE.iter g (hs_po hs).hsi_inv
556-
| FeHoareF hf -> g (ehf_pr hf).inv; g (ehf_po hf).inv
557-
| FeHoareS hs -> g (ehs_pr hs).inv; g (ehs_po hs).inv
558-
| FbdHoareF bhf -> g (bhf_pr bhf).inv; g (bhf_po bhf).inv; g (bhf_bd bhf).inv
559-
| FbdHoareS bhs -> g (bhs_pr bhs).inv; g (bhs_po bhs).inv; g (bhs_bd bhs).inv
560-
| FequivF ef -> g (ef_pr ef).inv; g (ef_po ef).inv
561-
| FequivS es -> g (es_pr es).inv; g (es_po es).inv
562-
| FeagerF eg -> g (eg_pr eg).inv; g (eg_po eg).inv
563-
| Fpr pr -> g pr.pr_args; g pr.pr_event.inv
544+
| Fop _ -> state
545+
546+
| Fquant (_ , _ , f1) -> tx state f1
547+
| Fif (f1, f2, f3) -> List.fold_left tx state [f1; f2; f3]
548+
| Fmatch (b, fs, _) -> List.fold_left tx state (b :: fs)
549+
| Flet (_, f1, f2) -> List.fold_left tx state [f1; f2]
550+
| Fapp (f, fs) -> List.fold_left tx state (f :: fs)
551+
| Ftuple fs -> List.fold_left tx state fs
552+
| Fproj (f, _) -> tx state f
553+
554+
| FhoareF hf -> POE.fold tx (tx state (hf_pr hf).inv) (hf_po hf).hsi_inv
555+
| FhoareS hs -> POE.fold tx (tx state (hs_pr hs).inv) (hs_po hs).hsi_inv
556+
| FeHoareF hf -> List.fold_left tx state [(ehf_pr hf).inv; (ehf_po hf).inv]
557+
| FeHoareS hs -> List.fold_left tx state [(ehs_pr hs).inv; (ehs_po hs).inv]
558+
| FbdHoareF bhf -> List.fold_left tx state [(bhf_pr bhf).inv; (bhf_po bhf).inv; (bhf_bd bhf).inv]
559+
| FbdHoareS bhs -> List.fold_left tx state [(bhs_pr bhs).inv; (bhs_po bhs).inv; (bhs_bd bhs).inv]
560+
| FequivF ef -> List.fold_left tx state [(ef_pr ef).inv; (ef_po ef).inv]
561+
| FequivS es -> List.fold_left tx state [(es_pr es).inv; (es_po es).inv]
562+
| FeagerF eg -> List.fold_left tx state [(eg_pr eg).inv; (eg_po eg).inv]
563+
| Fpr pr -> List.fold_left tx state [pr.pr_args; pr.pr_event.inv]
564564

565+
(* -------------------------------------------------------------------- *)
566+
let f_iter (tx : form -> unit) (f : form) =
567+
f_fold (fun () f -> tx f) () f
565568

566569
(* -------------------------------------------------------------------- *)
567570
let form_exists g f =

src/ecCoreFol.mli

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ val f_node : form -> f_node
7676
(* not recursive *)
7777
val f_map : (EcTypes.ty -> EcTypes.ty) -> (form -> form) -> form -> form
7878
val f_iter : (form -> unit) -> form -> unit
79+
val f_fold : ('a -> form -> 'a) -> 'a -> form -> 'a
80+
7981
val form_exists: (form -> bool) -> form -> bool
8082
val form_forall: (form -> bool) -> form -> bool
8183

@@ -108,9 +110,15 @@ val f_lambda : bindings -> form -> form
108110

109111
val f_forall_mems : (EcIdent.t * memtype) list -> form -> form
110112

113+
val f_hoareF_r : sHoareF -> form
114+
val f_hoareS_r : sHoareS -> form
115+
111116
val f_hoareF : ss_inv -> xpath -> hs_inv -> form
112117
val f_hoareS : memtype -> ss_inv -> stmt -> hs_inv -> form
113118

119+
val f_eHoareF_r : eHoareF -> form
120+
val f_eHoareS_r : eHoareS -> form
121+
114122
val f_eHoareF : ss_inv -> xpath -> ss_inv -> form
115123
val f_eHoareS : memtype -> ss_inv -> EcCoreModules.stmt -> ss_inv -> form
116124

@@ -119,10 +127,16 @@ val f_eHoareS : memtype -> ss_inv -> EcCoreModules.stmt -> ss_inv -> form
119127
(* soft-constructors - bd hoare *)
120128
val hoarecmp_opp : hoarecmp -> hoarecmp
121129

130+
val f_bdHoareF_r : bdHoareF -> form
131+
val f_bdHoareS_r : bdHoareS -> form
132+
122133
val f_bdHoareF : ss_inv -> xpath -> ss_inv -> hoarecmp -> ss_inv -> form
123134
val f_bdHoareS : memtype -> ss_inv -> stmt -> ss_inv -> hoarecmp -> ss_inv -> form
124135

125136
(* soft-constructors - equiv *)
137+
val f_equivF_r : equivF -> form
138+
val f_equivS_r : equivS -> form
139+
126140
val f_equivF : ts_inv -> xpath -> xpath -> ts_inv -> form
127141
val f_equivS : memtype -> memtype -> ts_inv -> stmt -> stmt -> ts_inv -> form
128142

src/ecFol.ml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,6 +1104,25 @@ let rec one_sided_vs mem fp =
11041104
| Fapp (f, args) -> one_sided_vs mem f @ List.concat_map (one_sided_vs mem) args
11051105
| _ -> []
11061106

1107+
(* -------------------------------------------------------------------- *)
1108+
let filter_topand_form (test : form -> bool) =
1109+
let rec doit (f : form) =
1110+
match sform_of_form f with
1111+
| SFand (mode, (f1, f2)) -> begin
1112+
match doit f1, doit f2 with
1113+
| None, None -> None
1114+
| Some f, None | None, Some f -> Some f
1115+
| Some f1, Some f2 -> begin
1116+
match mode with
1117+
| `Sym -> Some (f_and f1 f2)
1118+
| `Asym -> Some (f_anda f1 f2)
1119+
end
1120+
end
1121+
| _ ->
1122+
if test f then Some f else None
1123+
in fun f -> doit f
1124+
1125+
(* -------------------------------------------------------------------- *)
11071126
let rec dump_f f =
11081127
let dump_quant q =
11091128
match q with

src/ecFol.mli

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,5 +260,8 @@ module DestrReal : sig
260260
val abs : form -> form
261261
end
262262

263+
(* -------------------------------------------------------------------- *)
264+
val filter_topand_form : (form -> bool) -> form -> form option
265+
263266
(* -------------------------------------------------------------------- *)
264267
val dump_f : form -> string

src/ecLowPhlGoal.ml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,41 @@ let push_memenvs_pre (hyps : LDecl.hyps) (f : form) =
330330
([ml; mr], hyps)
331331
| _ -> assert false
332332

333+
(* -------------------------------------------------------------------- *)
334+
type logicS = [
335+
| `Hoare of sHoareS
336+
| `BdHoare of bdHoareS
337+
| `Equiv of equivS
338+
| `EHoare of eHoareS
339+
]
340+
341+
let get_logicS (f : form) : logicS =
342+
match f.f_node with
343+
| FhoareS hs -> `Hoare hs
344+
| FbdHoareS hs -> `BdHoare hs
345+
| FequivS hs -> `Equiv hs
346+
| FeHoareS hs -> `EHoare hs
347+
| _ -> destr_error "<program logic> (S)"
348+
349+
let hoareS_read (env : env) (hs : sHoareS) : EcPV.pmvs =
350+
EcPV.form_read env PMVS.empty (f_hoareS_r hs)
351+
352+
let bdHoareS_read (env : env) (hs : bdHoareS) : pmvs =
353+
form_read env PMVS.empty (f_bdHoareS_r hs)
354+
355+
let equivS_read (env : env) (hs : equivS) : pmvs =
356+
form_read env PMVS.empty (f_equivS_r hs)
357+
358+
let eHoareS_read (env : env) (hs : eHoareS) : pmvs =
359+
form_read env PMVS.empty (f_eHoareS_r hs)
360+
361+
let logicS_read (env : env) (f : logicS) =
362+
match f with
363+
| `Hoare hs -> hoareS_read env hs
364+
| `BdHoare hs -> bdHoareS_read env hs
365+
| `Equiv hs -> equivS_read env hs
366+
| `EHoare hs -> eHoareS_read env hs
367+
333368
(* -------------------------------------------------------------------- *)
334369
exception InvalidSplit of codepos1
335370

src/ecPV.ml

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,83 @@ let is_read env is = is_read_r env PV.empty is
630630
let s_read env s = s_read_r env PV.empty s
631631
let f_read env f = f_read_r env PV.empty f
632632

633+
(* -------------------------------------------------------------------- *)
634+
type pmvs = PV.t Mid.t
635+
636+
module PMVS : sig
637+
val empty : pmvs
638+
end = struct
639+
let empty : pmvs =
640+
Mid.empty
641+
end
642+
643+
(* -------------------------------------------------------------------- *)
644+
let form_read (env : env) (pvs : pmvs) =
645+
let rec doit (bds : Sid.t) (pvs : pmvs) (f : form) =
646+
match f.f_node with
647+
| Fpvar (_, m) when Sid.mem m bds ->
648+
pvs
649+
650+
| Fpvar (pv, m) ->
651+
Mid.change
652+
(fun pvs ->
653+
pvs
654+
|> Option.value ~default:PV.empty
655+
|> PV.add env pv f.f_ty
656+
|> Option.some)
657+
m pvs
658+
659+
| Fquant (_, subbds, f) ->
660+
let bds =
661+
List.fold_left
662+
(fun bds -> function _ -> bds)
663+
bds subbds in
664+
doit bds pvs f
665+
666+
| FhoareF hs ->
667+
let bds = Sid.add hs.hf_m bds in
668+
POE.fold (doit bds) (doit bds pvs (hf_pr hs).inv) (hf_po hs).hsi_inv
669+
670+
| FhoareS hs ->
671+
let bds = Sid.add (fst hs.hs_m) bds in
672+
POE.fold (doit bds) (doit bds pvs (hs_pr hs).inv) (hs_po hs).hsi_inv
673+
674+
| FbdHoareF hs ->
675+
let subbds = Sid.add hs.bhf_m bds in
676+
List.fold_left
677+
(doit subbds) (doit bds pvs (bhf_bd hs).inv)
678+
[(bhf_pr hs).inv; (bhf_po hs).inv]
679+
680+
| FbdHoareS hs ->
681+
let subbds = Sid.add (fst hs.bhs_m) bds in
682+
List.fold_left
683+
(doit subbds) (doit bds pvs (bhs_bd hs).inv)
684+
[(bhs_pr hs).inv; (bhs_po hs).inv]
685+
686+
| FequivF hs ->
687+
let bds = List.fold_left ((^~) Sid.add) bds [] in
688+
List.fold_left (doit bds) pvs [(ef_pr hs).inv; (ef_po hs).inv]
689+
690+
| FequivS hs ->
691+
let bds = List.fold_left ((^~) Sid.add) bds [] in
692+
List.fold_left (doit bds) pvs [(es_pr hs).inv; (es_po hs).inv]
693+
694+
| FeHoareF hs ->
695+
let bds = Sid.add hs.ehf_m bds in
696+
List.fold_left (doit bds) pvs [(ehf_pr hs).inv; (ehf_po hs).inv]
697+
698+
| FeHoareS hs ->
699+
let bds = Sid.add (fst hs.ehs_m) bds in
700+
List.fold_left (doit bds) pvs [(ehs_pr hs).inv; (ehs_po hs).inv]
701+
702+
| Fpr pr ->
703+
let pvs = doit bds pvs pr.pr_args in
704+
let pvs = doit (Sid.add pr.pr_mem bds) pvs pr.pr_event.inv in
705+
pvs
706+
707+
| _ -> f_fold (doit bds) pvs f
708+
in fun f -> doit Sid.empty pvs f
709+
633710
(* -------------------------------------------------------------------- *)
634711
exception EqObsInError
635712

src/ecPV.mli

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ val is_read : instr list pvaccess0
148148
val s_read : stmt pvaccess0
149149
val f_read : xpath pvaccess0
150150

151+
(* -------------------------------------------------------------------- *)
152+
type pmvs = PV.t EcIdent.Mid.t
153+
154+
module PMVS : sig
155+
val empty : pmvs
156+
end
157+
158+
val form_read : env -> pmvs -> form -> pmvs
159+
151160
(* -------------------------------------------------------------------- *)
152161
exception EqObsInError
153162

0 commit comments

Comments
 (0)