Skip to content

Commit 4fc93e8

Browse files
committed
Add one side while rule with lossless
1 parent 13acf05 commit 4fc93e8

File tree

1 file changed

+144
-2
lines changed

1 file changed

+144
-2
lines changed

src/phl/ecPhlWhile.ml

Lines changed: 144 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,144 @@ let t_equiv_while_disj_r side vrnt inv tc =
339339

340340
FApi.xmutate1 tc `While [b_concl; concl]
341341

342+
(* -------------------------------------------------------------------- *)
343+
344+
module Truc = struct
345+
exception CannotTranslate
346+
347+
let form_of_expr env mother mh =
348+
let map = ref (Mid.add mother (EcPV.PVMap.create env) Mid.empty) in
349+
350+
let rec aux fp =
351+
match fp.f_node with
352+
| Fint z -> e_int z
353+
| Flocal x -> e_local x fp.f_ty
354+
355+
| Fop (p, tys) -> e_op p tys fp.f_ty
356+
| Fapp (f, fs) -> e_app (aux f) (List.map aux fs) fp.f_ty
357+
| Ftuple fs -> e_tuple (List.map aux fs)
358+
| Fproj (f, i) -> e_proj (aux f) i fp.f_ty
359+
360+
| Fif (c, f1, f2) ->
361+
e_if (aux c) (aux f1) (aux f2)
362+
363+
| Fmatch (c, bs, ty) ->
364+
e_match (aux c) (List.map aux bs) ty
365+
366+
| Flet (lp, f1, f2) ->
367+
e_let lp (aux f1) (aux f2)
368+
369+
| Fquant (kd, bds, f) ->
370+
e_quantif (auxkd kd) (List.map auxbd bds) (aux f)
371+
372+
| Fpvar (pv, m) ->
373+
if EcIdent.id_equal m mh then
374+
e_var pv fp.f_ty
375+
else
376+
let bds = odfl (EcPV.PVMap.create env) (Mid.find_opt m !map) in
377+
let idx =
378+
match EcPV.PVMap.find pv bds with
379+
| None ->
380+
let pfx = EcIdent.name m in
381+
let pfx = String.sub pfx 1 (String.length pfx - 1) in
382+
let x = symbol_of_pv pv in
383+
let x = EcIdent.create (x ^ "_" ^ pfx) in
384+
let bds = EcPV.PVMap.add pv (x, fp.f_ty) bds in
385+
map := Mid.add m bds !map; x
386+
| Some (x, _) -> x
387+
388+
in e_local idx fp.f_ty
389+
390+
| Fglob _
391+
| FhoareF _ | FhoareS _
392+
| FeHoareF _ | FeHoareS _
393+
| FbdHoareF _ | FbdHoareS _
394+
| FequivF _ | FequivS _
395+
| FeagerF _ | Fpr _ -> raise CannotTranslate
396+
397+
and auxkd (kd : quantif) : equantif =
398+
match kd with
399+
| Lforall -> `EForall
400+
| Lexists -> `EExists
401+
| Llambda -> `ELambda
402+
403+
and auxbd ((x, bd) : binding) =
404+
match bd with
405+
| GTty ty -> (x, ty)
406+
| _ -> raise CannotTranslate
407+
408+
in fun f -> let e = aux f in (e, !map)
409+
end
410+
411+
let t_equiv_ll_while_disj_r side inv tc =
412+
let env = FApi.tc1_env tc in
413+
let es = tc1_as_equivS tc in
414+
let s, m_side, m_other =
415+
match side with
416+
| `Left -> es.es_sl, es.es_ml, es.es_mr
417+
| `Right -> es.es_sr, es.es_mr, es.es_ml in
418+
let (e, c), s = tc1_last_while tc s in
419+
let e = form_of_expr (EcMemory.memory m_side) e in
420+
421+
let ll =
422+
let evs = tc1_as_equivS tc in
423+
424+
let xhyps =
425+
let mtypes = Mid.of_list [evs.es_ml; evs.es_mr] in
426+
427+
fun m fp ->
428+
let fp =
429+
Mid.fold (fun mh pvs fp ->
430+
let mty = Mid.find_opt mh mtypes in
431+
let fp =
432+
EcPV.Mnpv.fold (fun pv (x, ty) fp ->
433+
f_let1 x (f_pvar pv ty mh) fp)
434+
(EcPV.PVMap.raw pvs) fp
435+
in f_forall_mems [mh, oget mty] fp)
436+
m fp
437+
in fp
438+
in
439+
440+
let ml = EcMemory.memory evs.es_ml in
441+
let subst = Fsubst.f_bind_mem Fsubst.f_subst_id ml mhr in
442+
let inv = Fsubst.f_subst subst inv in
443+
let e, m = Truc.form_of_expr env (EcMemory.memory evs.es_mr) ml e in
444+
let c = s_while (e, c) in
445+
xhyps m
446+
(f_bdHoareS (mhr, EcMemory.memtype evs.es_ml) inv c f_true FHeq f_r1)
447+
in
448+
449+
(* 1. The body preserves the invariant and the loop is lossless. *)
450+
451+
let m_other' = (EcIdent.create "&m", EcMemory.memtype m_other) in
452+
453+
let smem = Fsubst.f_subst_id in
454+
let smem = Fsubst.f_bind_mem smem (EcMemory.memory m_side ) mhr in
455+
let smem = Fsubst.f_bind_mem smem (EcMemory.memory m_other) (EcMemory.memory m_other') in
456+
457+
let b_pre = f_and_simpl inv e in
458+
let b_pre = Fsubst.f_subst smem b_pre in
459+
let b_post = inv in
460+
let b_post = Fsubst.f_subst smem b_post in
461+
let b_concl = f_bdHoareS (mhr, EcMemory.memtype m_side) b_pre c b_post FHeq f_r1 in
462+
let b_concl = b_concl in
463+
let b_concl = f_forall_mems [m_other'] b_concl in
464+
465+
(* 2. WP of the while *)
466+
let post = f_imps_simpl [f_not_simpl e; inv] es.es_po in
467+
let term_condition = f_imps_simpl [inv] (f_not_simpl e) in
468+
let post = f_and term_condition post in
469+
let modi = s_write env c in
470+
let post = generalize_mod env (EcMemory.memory m_side) modi post in
471+
let post = f_and_simpl inv post in
472+
let concl =
473+
match side with
474+
| `Left -> f_equivS_r { es with es_sl = s; es_po=post; }
475+
| `Right -> f_equivS_r { es with es_sr = s; es_po=post; }
476+
in
477+
478+
FApi.xmutate1 tc `While [b_concl; ll; concl]
479+
342480
(* -------------------------------------------------------------------- *)
343481
let t_equiv_while_r inv tc =
344482
let env = FApi.tc1_env tc in
@@ -374,6 +512,7 @@ let t_bdhoare_while_rev_geq = FApi.t_low4 "bdhoare-while" t_bdhoare_while_rev_ge
374512
let t_bdhoare_while_rev = FApi.t_low1 "bdhoare-while" t_bdhoare_while_rev_r
375513
let t_equiv_while = FApi.t_low1 "equiv-while" t_equiv_while_r
376514
let t_equiv_while_disj = FApi.t_low3 "equiv-while" t_equiv_while_disj_r
515+
let t_equiv_ll_while_dish = FApi.t_low2 "equiv-while" t_equiv_ll_while_disj_r
377516

378517
(* -------------------------------------------------------------------- *)
379518
let process_while side winfos tc =
@@ -400,7 +539,6 @@ let process_while side winfos tc =
400539
| Some vrnt, None ->
401540
let _, phi = TTC.tc1_process_Xhl_formula tc phi in
402541
let _, vrnt = TTC.tc1_process_Xhl_form tc tint vrnt in
403-
404542
t_bdhoare_while phi vrnt tc
405543

406544
| Some vrnt, Some (`Bd (k, eps)) ->
@@ -410,7 +548,6 @@ let process_while side winfos tc =
410548
let _, eps = TTC.tc1_process_Xhl_form tc treal eps in
411549

412550
t_bdhoare_while_rev_geq phi vrnt k eps tc
413-
414551
| None, None ->
415552
let _, phi = TTC.tc1_process_Xhl_formula tc phi in
416553
t_bdhoare_while_rev phi tc
@@ -430,6 +567,11 @@ let process_while side winfos tc =
430567
(TTC.tc1_process_prhl_formula tc phi)
431568
tc
432569

570+
| Some side, None ->
571+
t_equiv_ll_while_dish side
572+
(TTC.tc1_process_prhl_formula tc phi)
573+
tc
574+
433575
| _ -> tc_error !!tc "invalid arguments"
434576
end
435577

0 commit comments

Comments
 (0)