(** Heavily annotated for a tutorial introduction. *)
(** First, import the entire Floyd proof automation system, which includes ** the VeriC program logic and the MSL theory of separation logic**)
(** Import the [reverse.v] file, which is produced by CompCert's clightgen ** from reverse.c.   The file reverse.v defines abbreviations for identifiers ** (variable names, etc.) of the C program, such as _head, _reverse. ** It also defines "prog", which is the entire abstract syntax tree ** of the C program *)
(* The C programming language has a special namespace for struct ** and union identifiers, e.g., "struct foo {...}".  Some type-based operators ** in the program logic need access to an interpretation of this namespace, ** i.e., the meaning of each struct-identifier such as "foo".  The next ** line (which looks identical for any program) builds this ** interpretation, called "CompSpecs" *)
Instance CompSpecs : compspecs. make_compspecs prog. Defined.
(** Calculate the "types-of-global-variables" specification ** directly from the program *)
Definition Vprog : varspecs. mk_varspecs prog. Defined.
(** A convenience definition *)
Definition t_struct_list := Tstruct _list noattr.
(** Inductive definition of linked lists *)
Fixpoint listrep (sigma: list val) (x: val) : mpred :=
match sigma with
| h::hs =>
EX y:val,
data_at Tsh t_struct_list (h,y) x  *  listrep hs y
| nil =>
!! (x = nullval) && emp
end.
Arguments listrep sigma x : simpl never.
(** Whenever you define a new spatial operator, such as ** [listrep] here, it's useful to populate two hint databases. ** The [saturate_local] hint is a lemma that extracts ** pure propositional facts from a spatial fact. ** The [valid_pointer] hint is a lemma that extracts a ** valid-pointer fact from a spatial lemma. **)
Hint Resolve listrep_local_facts : saturate_local.
Hint Resolve listrep_valid_pointer : valid_pointer.
(** Specification of the [reverse] function.  It characterizes ** the precondition required for calling the function, ** and the postcondition guaranteed by the function. **)
Definition reverse_spec :=
DECLARE _reverse
WITH sigma : list val, p: val
PRE  [ _p OF (tptr t_struct_list) ]
PROP ()
LOCAL (temp _p p)
SEP (listrep sigma p)
POST [ (tptr t_struct_list) ]
EX q:val,
PROP () LOCAL (temp ret_temp q)
SEP (listrep(rev sigma) q).
(** The global function spec, characterizing the ** preconditions/postconditions of all the functions ** that your proved-correct program will call. ** Normally you include all the functions here, but ** in this tutorial example we include only one. *)
Definition Gprog : funspecs :=
ltac:(with_library prog [ reverse_spec ]).

(** For each function definition in the C program, prove that the ** function-body (in this case, f_reverse) satisfies its specification ** (in this case, reverse_spec). **)
Lemma body_reverse: semax_body Vprog Gprog
f_reverse reverse_spec.