NB: This Coq documentation contains a revised version of the Coq implementation of these papers [1], [2], [3], [4], and is also the support for ongoing research. A partial archive (14/01/2001) is available at here. Drop us a line if you are interested in a complete, up-to-date archive.

Library C_seplog

Require Import ssreflect ssrbool.
Require Import ZArith_ext Lists_ext.
Require Import machine_int.
Import MachineInt.
Require Import C_types C_expr C_bipl C_cmd.

Local Open Scope heap_scope.
Local Open Scope minC_expr_scope.
Local Open Scope minC_cmd_scope.
Local Open Scope minC_assert_scope.
Local Open Scope minC_types.

Definition wp_assign (t : typ) (x : var) (e : exp) (P : assert) : assert :=
  fun s h => exists v, [ e ]_ s = Some v /\
    typof s (var_e x) =ot _ctxt s ot= t /\
    typof s e =ot _ctxt s ot= t /\
    P (store_upd x v s) h.

Definition wp_lookup tx (x : var) (e : exp) (P : assert) : assert := fun s h =>
  wf_tstore (_tstore s) /\
  typof s (var_e x) =ot _ctxt s ot= tx /\
  typof s e =ot _ctxt s ot= ptyp tx /\
  exists p, [ e ]_s = Some (pval p) /\
    exists v, heap_get (Zabs_nat (u2Z p)) tx h = Some v /\
      P (store_upd x v s) h.

Definition wp_mutation (e e' : exp) (P : assert) : assert := fun s h =>
  wf_tstore (_tstore s) /\
  exists p, [ e ]_ s = Some (pval p) /\
    exists t, typof s e =ot _ctxt s ot= ptyp t /\
      exists v, heap_get (Zabs_nat (u2Z p)) t h = Some v /\
        exists v', [ e' ]_ s = Some v' /\
          typof s e' =ot (_ctxt s) ot= t /\
          P s (heap_upd (Zabs_nat (u2Z p)) v' t h).

Definition wp_malloc t (x : var) (wft_t : wft t) (e : exp) (P : assert) : assert :=
  fun s h =>
    typof s (var_e x) =ot _ctxt s ot= ptyp t /\
    cover (_ctxt s) t /\
    complete (_ctxt s) /\
    forall a (lst : list exp) v,
      h # ctrl a ->
      seq_ext.dis (hp.dom h) (seq_ext.ran a (Zabs_nat (u2Z v) * sizeof t)) ->
      seq_ext.dis (seq_ext.ran a (Zabs_nat (u2Z v) * sizeof t)) (hp.dom (ctrl a)) ->
      [ e ]_ s = Some (bval32 v) ->
      List.length lst = Zabs_nat (u2Z v) ->
      block_len _ (ctrl a) (refl_equal _) = (List.length lst * sizeof t)%nat ->
      (((fun _ h => h = ctrl a) **
        cst_pe wft_t (Z2u ptr_len (Z_of_nat a)) |% t %> lst) -*
      wp_assign (ptyp t) x (cst_pe wft_t (Z2u ptr_len (Z_of_nat a))) P) s h.

Definition wp_free (e : exp) (P : assert) := fun s h => exists p,
    [ e ]_s = Some (pval p) /\
    ctrl (Zabs_nat (u2Z p)) [<=m] h /\
    incl (seq (Zabs_nat (u2Z p)) (Block_len (ctrl (Zabs_nat (u2Z p))))) (seq_ext.s2l (hp.dom h)) /\
    P s (h [\m]
      seq_ext.l2s (List.seq (Zabs_nat (u2Z p)) (Block_len (ctrl (Zabs_nat (u2Z p))))) [\m]
      hp.dom (ctrl (Zabs_nat (u2Z p)))).

Inductive hoare0 : assert -> cmd0 -> assert -> Prop :=
| hoare0_skip: forall P, hoare0 P skip P
| hoare0_assign : forall P t x e, hoare0 (wp_assign t x e P) (x <- e) P
| hoare0_lookup : forall P tx x e, hoare0 (wp_lookup tx x e P) (x <-* e) P
| hoare0_mutation : forall P e e', hoare0 (wp_mutation e e' P) (e *<- e') P
| hoare0_malloc : forall P tx (x : var) e (H : wft (tx)),
  hoare0 (wp_malloc tx x H e P) (x <-malloc e) P
| hoare0_free : forall P (e : exp), hoare0 (wp_free e P) (free e) P.

Notation "'hoare_semantics'" :=
  (@while.hoare_semantics store hp.t _ exec0 _ (fun eb s => [ eb ]b_ (fst s))) : minC_hoare_scope.

Local Open Scope minC_hoare_scope.

Require Import eqtype.

Lemma soundness0 : forall (P Q : assert) c,
  hoare0 P c Q -> hoare_semantics P c Q.

Notation "'wp_semantics'" := (@while.wp_semantics store hp.t _ exec0 _ (fun eb s => [ eb ]b_ (fst s)))
  : temp_minC_hoare_scope.

Notation "{{ P }} c {{ Q }}" := (while.hoare store hp.t
  cmd0 _ (fun eb s => [ eb ]b_ (fst s)) (hoare0) P c Q) (at level 82, no associativity) : temp_minC_hoare_scope.

Axiom wp0 : cmd0 -> assert -> assert.

Axiom wp0_no_err : forall s h c P, wp0 c P s h -> ~ (Some (s, h) -- c ----> None).

Local Open Scope temp_minC_hoare_scope.

Axiom wp_semantics_sound0 : forall (c:cmd0) P, {{ wp_semantics c P }} c {{ P }}.


Module MINC_Hoare <: while.WHILE_HOARE.

Include MINC_Semop.

Definition assert := store -> heap -> Prop.

Definition wp0 : cmd0 -> assert -> assert := wp0.
Definition wp0_no_err : forall s h c P, wp0 c P s h -> ~ (Some (s,h) -- c ----> None) := wp0_no_err.

Definition hoare0 : assert -> cmd0 -> assert -> Prop := hoare0.

Definition hoare : assert -> cmd -> assert -> Prop := @while.hoare store heap
  cmd0 expr_b eval_b hoare0.

Definition soundness0 : forall P Q c, hoare0 P c Q -> hoare_semantics P c Q := soundness0.

Definition wp_semantics_sound0 : forall (c:cmd0) P, {{ wp_semantics c P }} c {{ P }} :=
  fun c => wp_semantics_sound0 c.

End MINC_Hoare.


Local Close Scope temp_minC_hoare_scope.

Notation "{{ P }} c {{ Q }}" := (@while.hoare store hp.t
  cmd0 bexp (fun eb s => [ eb ]b_ (fst s)) (hoare0) P c Q) (at level 82, no associativity) : minC_hoare_scope.

Module minc_hoare_prop_m := while.While_Hoare_Prop MINC_Hoare.

Lemma hoare_assign' : forall t (Q P : assert) x e,
  P ===> wp_assign t x e Q -> {{ P }} x <- e {{ Q }}.

Lemma hoare_assign : forall t R P Q x e c, P ===> wp_assign t x e R ->
  {{ R }} c {{ Q }} -> {{ P }} x <- e ; c {{ Q }}.

Lemma hoare_lookup' : forall t (Q P : assert) x e,
  P ===> (wp_lookup t x e Q) -> {{ P }} x <-* e {{ Q }}.

Lemma hoare_lookup_back : forall t x e P,
  {{ fun s h => wf_tstore (_tstore s) /\
    typof s (var_e x) =ot _ctxt s ot= t /\
    typof s e =ot _ctxt s ot= ptyp t /\
    exists p, [ e ]_s = Some (pval p) /\
      exists e0, (e |~ t ~> e0 **
        (e |~ t ~> e0 -* wp_assign t x e0 P)) s h }}
  x <-* e
  {{ P }}.

Lemma hoare_lookup_back'' : forall t P Q R x e c,
  P ===> (fun s h =>
    wf_tstore (_tstore s) /\
    typof s (var_e x) =ot _ctxt s ot= t /\
    typof s e =ot _ctxt s ot= ptyp t /\
    exists p, [ e ]_s = Some (pval p) /\
    exists e0, (e |~ t ~> e0 **
      (e |~ t ~> e0 -* wp_assign t x e0 R)) s h) ->
  {{ R }} c {{ Q }} -> {{ P }} x <-* e; c {{ Q }}.

Lemma hoare_false: forall c P, {{ FF }} c {{ P }}.

Local Open Scope minC_cmd_scope.

Fixpoint modified_vars (c : @while.cmd _ bexp) {struct c} : list var :=
  match c with
    | skip => nil
    | x <- e => x :: nil
    | x <-* e => x :: nil
    | e *<- f => nil
    | x <-malloc e => x :: nil
    | free e => nil
    | while.seq c1 c2 => modified_vars c1 ++ modified_vars c2
    | while.ifte a c1 c2 => modified_vars c1 ++ modified_vars c2
    | while.while a c1 => modified_vars c1
   end.

Definition inde (l : list var) (P : assert) := forall s h,
  (forall x v, In x l -> (P s h <-> P (store_upd x v s) h)).

Lemma inde_seq : forall R c d, inde (modified_vars (c ; d)) R ->
  inde (modified_vars c) R /\ inde (modified_vars d) R.

Lemma inde_ifte : forall R b c d, inde (modified_vars (while.ifte b c d)) R ->
  inde (modified_vars c) R /\ inde (modified_vars d) R.

Lemma inde_upd_tstore : forall (P : assert) x z s h,
  inde (x :: List.nil) P -> P s h -> P (store_upd x z s) h.
Require Import String_ext.
Require Import nodup.

Lemma frame_rule0 : forall P c Q, hoare0 P c Q ->
  forall R, inde (modified_vars c) R -> {{ P ** R }} c {{ Q ** R }}.

Lemma frame_rule : forall P c Q, {{ P }} c {{ Q }} ->
  forall R, inde (modified_vars c) R -> {{ P ** R }} c {{ Q ** R }}.

Local Open Scope minC_assert_scope.

Lemma hoare_mutation_global : forall P t e e',
  {{ (fun s' h' =>
    wf_tstore (_tstore s') /\
    typof s' e' = Some t /\
    exists e'', (e |~ t ~> e'') s' h') ** P }}
  e *<- e'
  {{ (fun s h => (e |~ t ~> e') s h) **
    P}}.

Lemma hoare_mutation_backwards : forall P t e e',
  {{ fun s h => wf_tstore (_tstore s) /\
    typof s e' = Some t /\
    exists e'', (e |~ t ~> e'' **
    (e |~ t ~> e' -* P)) s h }}
  e *<- e'
  {{ P }}.

Lemma hoare_mutation_backwards' : forall Q P t e1 e2,
  P ===> (fun s h => wf_tstore (_tstore s) /\
    typof s e2 = Some t /\
    exists e'', (e1 |~ t ~> e'' ** (e1 |~ t ~> e2 -* Q)) s h) ->
  {{ P }} e1 *<- e2 {{ Q }}.

Lemma hoare_mutation_backwards'' : forall Q P R e1 t e2 c,
  P ===> (fun s h =>
   wf_tstore (_tstore s) /\
    typof s e2 = Some t /\
    exists e'', (e1 |~ t ~> e'' **
      (e1 |~ t ~> e2 -* R)) s h) ->
  {{ R }} c {{ Q }} -> {{ P }} e1 *<- e2 ; c {{ Q }}.