Library C_reverse_list_triple

From mathcomp Require Import ssreflect ssrfun ssrbool eqtype seq tuple.
Require Import ZArith_ext String_ext ssrnat_ext seq_ext.
Require Import machine_int.
Import MachineInt.
Require Import C_types C_types_fp C_value C_expr C_seplog.
Require Import C_reverse_list_header.
Import C_Seplog_m.

Local Open Scope string_scope.
Local Open Scope C_types_scope.
Local Open Scope C_value_scope.
Local Open Scope C_cmd_scope.

reverse_list using lemmas from the library (no tactics)

Lemma reverse_list_correct l :
  {{ seplogClst_e l __i }} reverse_list {{ seplogClst_e (rev l) __ret }}.
Proof.
rewrite /reverse_list.

_ret <- NULL; 

apply hoare_assign_seq_stren with (fun s h => seplogClst l ([ __i ]_ s) s h /\ [ __ret ]_s = pv0).
  move=> s h H.
  apply wp_assign_c.
  rewrite eval_store_upd_notin //.
  split; first by move: H; apply seplogClst_inde.
  by rewrite -subst_exp_store_upd.

While \~b \b __i \= NULL {{ 

apply hoare_while_invariant with (fun s h => exists l1 l2, l = (l1 ++ l2)%SEQ /\
  (seplogClst (rev l1) [ __ret ]_s ** seplogClst l2 [ __i ]_s) s h).
  - move=> s h H.
    exists nil, l => /=.
    split => //.
    case: H => /= H Hret.
    rewrite -(hp.unioneh h).
    apply con_c => //.
    + by Disj.
    + rewrite Hret; by constructor.
  - move=> s h [] [l1 [l2 [Hl Hmem]]].
    rewrite /C_definition.eval_b /C_StateBipl.eval_b /= beval_neg_not negbK beval_eq_p_eq.
    move/eqP => H.
    rewrite H in Hmem.
    case: Hmem => h1 h2 h1h2 H1 H2.
    inversion H2; clear H2; last by done.
    subst.
    by rewrite cats0 hp.unionhe.

_rem <-* __i &-> _next; 

apply hoare_seq with (fun s h => exists l1 hd l2, l = cat l1 (hd :: l2) /\
    [ __i ]_ s <> pv0 /\ (seplogClst (rev l1) ([ __ret ]_s) **
      ([ __i ]_s |lV~> mk_cell hd (ptr<=phy [ __rem ]_s)) **
      seplogClst l2 [ __rem ]_s) s h).
  apply hoare_lookup_fldp_stren => s h [] [] l1 [] l2 [] Hl Hh.
  rewrite /C_Semop0.eval_b /C_StateBipl.eval_b beval_neg_not => /negP H.
  have {H}H' : [ __i ]_s <> pv0.
    move => H'; apply H => {H} /=.
    Transparent beval eval.
    simpl. simpl in H'. rewrite H' eq_refl.
    Opaque beval eval.
    by apply not_is_zero_1.
  case: Hh => h1 h2 h1h2 H1 H2.
  move: H1; set i := [%"i"]_s => H1.
  inversion H2; subst; clear H2; first by rewrite H3 in H'.
  apply mkWpLookupFldpConv with (pv := p) (lvs := list_header h0 (ptr<=phy p)) (lv := log_of_ptr _ _ erefl (ptr<=phy p)).
  - by rewrite /= -Eqdep.Eq_rect_eq.eq_rect_eq.
  - by rewrite /phylog_conv /= ptr_of_phyK.
  - split.
    + rewrite (_ : h1 \U (h3 \U h4) = h3 \U (h1 \U h4)); last by Equal.
      apply con_c => //.
      rewrite hp.unionC //; by Disj.
    + apply wp_assign_c.
      exists l1, h0, t.
      split => //.
      split; first by rewrite eval_store_upd_notin.
      apply con_c => //.
      - rewrite eval_store_upd_notin //.
        by eapply seplogClst_inde; eauto.
      - rewrite -subst_exp_store_upd /=.
        apply con_c => //.
        by rewrite eval_store_upd_notin.
        by eapply seplogClst_inde; eauto.

__i &-> _next *<- __ret; 

apply hoare_seq with (fun s h => exists l1 hd l2, l = (l1 ++ (hd :: l2))%SEQ /\
    [ __i ]_ s <> pv0 /\
    (seplogClst (rev (rcons l1 hd)) ([ __i ]_s) ** seplogClst l2 ([ __rem ]_s)) s h).
  apply hoare_L_ex => l1.
  apply hoare_L_ex => hd.
  apply hoare_L_ex => l2.
  apply hoare_R_ex; exists l1.
  apply hoare_R_ex; exists hd.
  apply hoare_R_ex; exists l2.
  apply hoare_pure_left; first by done.
  split; first by done.
  set c := __i &-> _next *<- __ret.
  set R := seplogClst_e l2 __rem.
  set P := fun s h => [ __i ]_ s <> pv0 /\
    (seplogClst (rev l1) [ __ret ]_ s ** [ __i ]_ s |lV~> mk_cell hd (ptr<=phy [ __rem ]_ s)) s h.
  set Q := fun s h => [ __i ]_ s <> pv0 /\ (seplogClst (rev (rcons l1 hd)) [ __i ]_ s) s h.
  suff PcQ : {{ P }} c {{ Q }}.
    have inde_R : inde_cmd c R by done.
    eapply hoare_conseq; last first.
    - by apply (frame_rule_R _ _ _ PcQ _ inde_R).
    - rewrite /P /R => s h /= [] Hneq H.
      case: H => h1 h2 h1h2 H1 H2.
      case: H2 h1h2 => h21 h22 h21h22 H21 H22 h1h2.
      rewrite (_ : h1 \U (h21 \U h22) = (h1 \U h21) \U h22); last by Equal.
      apply con_c => //; first by Disj.
      split => //.
      apply con_c => //; by Disj.
    - rewrite /Q /R => s h //= H.
      case: H => h1 h2 h1h2 [] H11 H12 H2.
      by econstructor.
  rewrite /P /Q {P Q R}.
  apply hoare_weak with (fun s h => [ __i ]_ s <> pv0 /\
    ([ __i ]_ s |lV~> mk_cell hd (ptr<=phy [ __ret ]_ s) ** seplogClst (rev l1) [ __ret ]_ s ) s h ).
    move => s h //= [] Hneq.
    case=> h1 h2 h1h2 H1 H2.
    split; first by done.
    rewrite rev_rcons.
    econstructor => //=.
    by apply H1.
    exact H2.
  eapply hoare_stren with (fun s h => [ __i ]_ s <> pv0 /\
    ([ __i ]_ s |lV~> mk_cell hd (ptr<=phy [ __rem ]_ s) ** seplogClst (rev l1) [ __ret ]_ s ) s h).
    move => s h //= [] Hneq H.
    inversion H; subst; clear H.
    split; first by done.
    rewrite hp.unionC; last by Disj.
    constructor => //; first by Disj.
  set P := fun s h => [ __i ]_ s <> pv0 /\ ([ __i ]_ s |lV~> mk_cell hd (ptr<=phy [ __rem ]_ s)) s h.
  set Q := fun s h => [ __i ]_ s <> pv0 /\ ([ __i ]_ s |lV~> mk_cell hd (ptr<=phy [ __ret ]_ s)) s h.
  set R := fun s h => [ __i ]_ s <> pv0 /\ (seplogClst (rev l1) [ __ret ]_ s) s h.
  suff PcQ : {{ P }} c {{ Q }}.
    have inde_R : inde_cmd c R by done.
    eapply hoare_conseq; last first.
      by apply (frame_rule_R _ _ _ PcQ _ inde_R).
      rewrite /P /R => s h //= [] Hneq [] h1 h2 h1h2 H1 H2.
      by econstructor.
    rewrite /Q /R => s h //= [] h1 h2 h1h2 [] H11 H12 [] H21 H22.
    by econstructor.
  rewrite /P /Q {P Q R} /mk_cell.
  apply hoare_and_left.
    move => s h s' h' Hc.
    suff : [ __i ]_s = [ __i ]_s' by move=> ->.
    inversion Hc; subst; clear Hc.
    by inversion H1; subst; clear H1.
  apply hoare_stren with (fun s h => exists k, k = [ __rem ]_ s /\
    ([ __i ]_ s |lV~> log_of_styp Clst _ Logic.eq_refl (list_header hd (ptr<=phy [ __rem ]_ s))) s h).
    move => s h /= H; by exists ([ __rem ]_ s).
  apply hoare_L_ex => k.
  apply hoare_stren with (fun s h =>
     ([ __i ]_ s |lV~> log_of_styp Clst _ Logic.eq_refl (list_header hd (ptr<=phy k))) s h).
    by move => s h /= [] ->.
  eapply hoare_weak; last by apply hoare_mutation_fldp_local_forward.
  move=> s h /= H.
  have : [ __ret ]_ s |x| (log_of_ptr _ _ erefl (ptr<=phy ([ __ret ]_ s))).
    by rewrite /phylog_conv /= ptr_of_phyK.
  move/(H _).
  by rewrite -Eqdep.Eq_rect_eq.eq_rect_eq.

_ret <- __i 

apply hoare_seq with (fun s h =>
  exists l1 hd l2, l = (l1 ++ (hd :: l2))%list /\
    (seplogClst (rev (rcons l1 hd)) ([ __ret ]_s) ** seplogClst l2 ([ __rem ]_s)) s h).
  apply hoare_assign_stren => s h [] l1 [] hd [] l2 [] Hl [] Heq.
  case => h1 h2 h1h2 H1 H2.
  apply wp_assign_c.
  exists l1, hd, l2.
  split; first by done.
  apply con_c => //; rewrite -subst_exp_store_upd /=; eapply seplogClst_inde; eauto.

_i <- __rem 

apply hoare_assign_stren => s h [] l1 [] hd [] l2 [] Hl.
case => h1 h2 h1h2 H1 H2.
apply wp_assign_c.
exists (rcons l1 hd), l2.
split; first by rewrite cat_rcons.
apply con_c => //; rewrite -subst_exp_store_upd /=; eapply seplogClst_inde; eauto.
Qed.