Skip to content

Commit ed61f01

Browse files
committed
New tactic: "case <-"
This tactic "inlines" tuple assignments, i.e. it transforms ``` (lv1,...,lvn) <- (e1,...,en); ``` in ``` lv1 <- e1; ... lvn <- en; ```
1 parent 5903e1f commit ed61f01

File tree

8 files changed

+73
-0
lines changed

8 files changed

+73
-0
lines changed

src/ecHiTacticals.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ and process1_phl (_ : ttenv) (t : phltactic located) (tc : tcenv1) =
193193
| Pinterleave info -> EcPhlSwap.process_interleave info
194194
| Pcfold info -> EcPhlCodeTx.process_cfold info
195195
| Pkill info -> EcPhlCodeTx.process_kill info
196+
| Pasgncase info -> EcPhlCodeTx.process_case info
196197
| Palias info -> EcPhlCodeTx.process_alias info
197198
| Pset info -> EcPhlCodeTx.process_set info
198199
| Pweakmem info -> EcPhlCodeTx.process_weakmem info

src/ecPV.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,9 @@ and i_read_r env r i =
622622
(* -------------------------------------------------------------------- *)
623623
type 'a pvaccess0 = env -> 'a -> PV.t
624624

625+
let lp_write env lp =
626+
lp_write_r env PV.empty lp
627+
625628
let i_write ?(except=Sx.empty) env i = i_write_r ~except env PV.empty i
626629
let is_write ?(except=Sx.empty) env is = is_write_r ~except env PV.empty is
627630
let s_write ?(except=Sx.empty) env s = s_write_r ~except env PV.empty s

src/ecPV.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ val f_read_r : xpath pvaccess
131131
(* -------------------------------------------------------------------- *)
132132
type 'a pvaccess0 = env -> 'a -> PV.t
133133

134+
val lp_write : lvalue pvaccess0
134135
val i_write : ?except:Sx.t -> instr pvaccess0
135136
val is_write : ?except:Sx.t -> instr list pvaccess0
136137
val s_write : ?except:Sx.t -> stmt pvaccess0

src/ecParser.mly

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3233,6 +3233,9 @@ phltactic:
32333233
| KILL s=side? o=codepos NOT STAR
32343234
{ Pkill (s, o, None) }
32353235

3236+
| CASE LARROW s=side? o=codepos
3237+
{ Pasgncase (s, o) }
3238+
32363239
| ALIAS s=side? o=codepos
32373240
{ Palias (s, o, None) }
32383241

src/ecParsetree.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,7 @@ type phltactic =
755755
| Poutline of outline_info
756756
| Pinterleave of interleave_info located
757757
| Pkill of (oside * codepos * int option)
758+
| Pasgncase of (oside * codepos)
758759
| Prnd of oside * semrndpos option * rnd_tac_info_f
759760
| Prndsem of bool * oside * codepos1
760761
| Palias of (oside * codepos * osymbol_r)

src/phl/ecPhlCodeTx.ml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
(* -------------------------------------------------------------------- *)
22
open EcUtils
3+
open EcParsetree
34
open EcAst
45
open EcTypes
56
open EcModules
@@ -293,3 +294,42 @@ let process_weakmem (side, id, params) tc =
293294
in
294295
let concl = f_imp h (FApi.tc1_goal tc) in
295296
FApi.xmutate1 tc `WeakenMem [concl]
297+
298+
(* -------------------------------------------------------------------- *)
299+
let process_case ((side, pos) : side option * codepos) (tc : tcenv1) =
300+
let (env, _, concl) = FApi.tc1_eflat tc in
301+
302+
let change (i : instr) =
303+
if not (is_asgn i) then
304+
tc_error !!tc "the code position should target an assignment";
305+
306+
let lv, e = destr_asgn i in
307+
308+
let pvl = EcPV.lp_write env lv in
309+
let pve = EcPV.e_read env e in
310+
let lv = lv_to_list lv in
311+
312+
if not (EcPV.PV.indep env pvl pve) then
313+
assert false;
314+
315+
let e =
316+
match lv, e.e_node with
317+
| [_], _ -> [e]
318+
| _ , Etuple es -> es
319+
| _ ,_ -> assert false in
320+
321+
let s = List.map2 (fun pv e -> i_asgn (LvVar (pv, e.e_ty), e)) lv e in
322+
323+
([], s)
324+
in
325+
326+
let kinds = [`Hoare `Stmt; `EHoare `Stmt; `PHoare `Stmt; `Equiv `Stmt] in
327+
328+
if not (EcLowPhlGoal.is_program_logic concl kinds) then
329+
assert false;
330+
331+
let s = EcLowPhlGoal.tc1_get_stmt side tc in
332+
let goals, s = EcMatching.Zipper.map pos change s in
333+
let concl = EcLowPhlGoal.hl_set_stmt side concl s in
334+
335+
FApi.xmutate1 tc `ProcCase (goals @ [concl])

src/phl/ecPhlCodeTx.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ val process_kill : oside * codepos * int option -> backward
1414
val process_alias : oside * codepos * psymbol option -> backward
1515
val process_set : oside * codepos * bool * psymbol * pexpr -> backward
1616
val process_cfold : oside * codepos * int option -> backward
17+
val process_case : oside * codepos -> backward
1718

1819
(* -------------------------------------------------------------------- *)
1920
val process_weakmem : (oside * psymbol * fun_params) -> backward

tests/asgncase.ec

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
(* -------------------------------------------------------------------- *)
2+
require import AllCore.
3+
4+
(* -------------------------------------------------------------------- *)
5+
module M = {
6+
proc f(x : int, y : int) = {
7+
var x', y' : int;
8+
9+
(x', y') <- (x, y);
10+
11+
return (x', y');
12+
}
13+
}.
14+
15+
(* -------------------------------------------------------------------- *)
16+
lemma L : hoare[M.f : arg = (0, 1) ==> res = (0, 1)].
17+
proof.
18+
proc.
19+
case <- 1.
20+
seq 1 : (x' = 0 /\ y = 1).
21+
- by auto.
22+
- by auto.
23+
qed.

0 commit comments

Comments
 (0)