CFEM.C.nonexpansive

Machinery for proving the nonexpansiveness of object-oriented interfaces.

All of this should be moved into VST.floyd, and documented in the reference manual or in Software Foundations vol. 5

Require Import VST.floyd.proofauto.

Import rmaps.
Import compcert_rmaps.RML.R.

Lemma approx_approx_S: (n: nat) (P: mpred), approx n (approx (S n) P) = approx n P.

Lemma approx_andp_prop: n P Q Q', approx n Q = approx n Q'
       approx n (andp (prop P) Q) = approx n (andp (prop P) Q').

Lemma approx_andp': n (P P' Q Q': mpred),
       approx n P = approx n P'
       approx n Q = approx n Q'
       approx n (andp P Q) = approx n (andp P' Q').

Lemma approx_sepcon': n (P P' Q Q': mpred),
  approx n P = approx n P'
  approx n Q = approx n Q'
  approx n (sepcon P Q) = approx n (sepcon P' Q').

Lemma approx_exp': (A: Type) (P1 P2: A mpred) (n: nat),
    ( x, approx n (P1 x) = approx n (P2 x))
    approx n (exp P1) = approx n (exp P2).

Lemma approx_func_ptr'':
   n fsig cc A P P' Q Q' v,
   ( x rho, approx n (P x rho) = approx n (P' x rho))
   ( x rho, approx n (Q x rho) = approx n (Q' x rho))
   approx (S n) (func_ptr' (NDmk_funspec fsig cc A P Q) v) =
   approx (S n) (func_ptr' (NDmk_funspec fsig cc A P' Q') v).

Create HintDb nonexpansive.

Ltac nonexpansive_prover :=
lazymatch goal with
  | |- args_super_non_expansive _intros ? ? ? ?
  | |- super_non_expansive _intros ? ? ? ?
  | |- approx ?n1 _ = approx ?n2 _first [constr_eq n1 n2 | fail 1 "Ltac nonexpansive prover requires equal approximation levels, but" n1"<>"n2]
  | _idtac end;
repeat match goal with
          | |- approx _ ?A = approx _ ?Bconstr_eq A B; reflexivity
          | |- approx _ (sepcon _ _) = approx _ (sepcon _ _) ⇒ apply approx_sepcon'
          | |- approx _ (sepcon _ _ _) = approx _ (sepcon _ _ _) ⇒ apply approx_sepcon'
          | |- approx _ (andp _ _) = approx _ (andp _ _) ⇒ apply approx_andp'
          | |- approx _ (andp _ _ _) = approx _ (andp _ _ _) ⇒ apply approx_andp'
          | |- approx _ (exp _) = approx _ (exp _) ⇒ apply approx_exp'; intro
          | |- approx _ (exp _ _) = approx _ (exp _ _) ⇒ apply approx_exp'; intro
          | |- approx (S _) (func_ptr' _ _) = approx (S _) (func_ptr' _ _) ⇒ apply approx_func_ptr''; intros
          | |- approx ?n (func_ptr' _ _) = approx ?n' (func_ptr' _ _) ⇒
                 constr_eq n n'; is_var n; destruct n as [ | n]; [rewrite !approx_0; reflexivity | ]
          | |- approx _ (PROPx _ _ _) = approx _ (PROPx _ _ _) ⇒ apply approx_andp'
          | |- approx _ (PARAMSx _ _ _) = approx _ (PARAMSx _ _ _) ⇒ apply approx_andp'
          | |- approx _ (GLOBALSx _ _ _) = approx _ (GLOBALSx _ _ _) ⇒ apply approx_andp'
          | |- approx _ (LOCALx _ _ _) = approx _ (LOCALx _ _ _) ⇒ apply approx_andp'
          | |- approx _ (SEPx _ _) = approx _ (SEPx _ _) ⇒ apply approx_sepcon'
          | |- approx _ (match ?x with __ end) = _destruct x
          | |- approx _ (match ?x with __ end _) = _destruct x
          | |- approx _ (match ?x with __ end _ _) = _destruct x
          | |- approx _ (match ?x with __ end _ _ _ ) = _destruct x
          | |- _progress rewrite ?approx_idem, ?approx_approx_S
          | |- _progress unfold argsassert2assert
          | |- _progress (change (fst (?A,_)) with A; change (snd (_,?B)) with B)
          | H: functors.MixVariantFunctor._functor _ _ |- _progress simpl in H
          | |- context [functors.MixVariantFunctor.fmap ?A ?B] ⇒
                  let b := constr: (functors.MixVariantFunctor.fmap A B) in
                   let b' := eval hnf in b in let b' := eval simpl in b' in change b with b'; cbv beta match
   end;
 auto with nonexpansive.