Hint Resolve list_cell_local_facts : saturate_local.
End LsegSpecial.
Module Links.
Section LIST2.
Context {cs: compspecs}.
Context  {list_structid: ident} {list_link: ident}{list_token: share -> val -> mpred}.
Definition vund  (ls: listspec list_structid list_link list_token) : elemtype ls :=
compact_prod_gen
(fun it => default_val (field_type (fst it) list_fields)) (@all_but_link list_link  list_fields).
Definition lseg (ls: listspec list_structid list_link list_token) (dsh psh: share)
(contents: list val) (x z: val) : mpred :=
LsegGeneral.lseg ls dsh psh (map (fun v => (v, vund ls)) contents) x z.

(* Specifications: *)
Lemma nonreadable_list_cell_eq:
forall (ls: listspec list_structid list_link list_token) sh v v' p,
~ readable_share sh ->
list_cell ls sh v p = list_cell ls sh v' p.
Lemma cell_share_join:
forall (ls: listspec list_structid list_link list_token) ash bsh psh p v,
sepalg.join ash bsh psh ->
list_cell ls ash v p * list_cell ls bsh v p = list_cell ls psh v p.
Lemma join_cell_link (ls: listspec list_structid list_link list_token):
forall v' ash bsh psh p v,
sepalg.join ash bsh psh ->
~ (readable_share ash) ->
readable_share bsh ->
list_cell ls ash v' p * list_cell ls bsh v p = list_cell ls psh v p.
Lemma lseg_unfold (ls: listspec list_structid list_link list_token): forall dsh psh contents v1 v2,
lseg ls dsh psh contents v1 v2 =
match contents with
| p::t => !! (p=v1 /\ ~ ptr_eq v1 v2) && EX tail: val,
!! is_pointer_or_null tail &&
list_token dsh v1 * list_cell ls dsh (vund ls) v1
* field_at psh list_struct (StructField list_link :: nil)
(valinject (nested_field_type list_struct (StructField list_link :: nil)) tail) v1
* lseg ls dsh psh t tail v2
| nil => !! (ptr_eq v1 v2) && emp
end.
Lemma lseg_eq (ls: listspec list_structid list_link list_token):
forall dsh psh l v ,
is_pointer_or_null v ->
lseg ls dsh psh l v v = !!(l=nil) && emp.