(*+ Resource maps *)
(** In this file: - common results about lists - definition of resource maps, ignoring problems related to step indexing *)
(*+ List functions *)
Fixpoint nth {A} (l : list A) i :=
match l with
| nil => None
| x :: l =>
match i with
| O => Some x
| S i => nth l i
end
end.
Fixpoint nth_upd {A} (l : list A) i x :=
match l with
| nil => nil
| y :: l =>
match i with
| O => x :: l
| S i => y :: nth_upd l i x
end
end.
Ltac ifeq :=
match goal with
[ H : context [ eq_nat_dec ?x ?x ] |- _ ] => destruct (eq_nat_dec x x) as [_|]; [|congruence]
| [ |- context [ eq_nat_dec ?x ?x ] ] => destruct (eq_nat_dec x x) as [_|]; [|congruence]
| [ H : context [ eq_nat_dec ?x ?y ] |- _ ] => destruct (eq_nat_dec x y)
| [ |- context [ eq_nat_dec ?x ?y ] ] => destruct (eq_nat_dec x y)
end.
(*+ Resource maps *)
(** Here, we avoid solving the indirection equation by abstracting over the desired properties, not worrying about step indexing to add predicates in the "memory" (i.e. the resource maps).  Note that it is also possible to instantiate the variable [lock] with a deep embedding of the desired resource invariants without cheating. *)
Variable lock : Set.
Definition val := (nat + lock)%type.
Definition map := nat -> option val.
Variable interp_lock : lock -> (map -> Prop).
Definition emptymap : map := fun _ => None.
Definition eqmap (m m' : map) := forall x, m x = m' x.
Instance eqmap_equiv : Equivalence eqmap.
Definition upd {A} (m : nat -> A) x e :=
fun y => if eq_nat_dec x y then e else m y.
Definition updatemap (m : map) (x e : nat) : option map :=
match m x with Some _ => Some (upd m x (Some (inl e))) | None => None end.
Definition assertmap (m : map) (x : nat) : Prop :=
match m x with Some (inl (S _)) => True | _ => False end.
(*+ Join relation on resources and resource maps *)
Definition joincell (a b : option val) : option (option val) :=
match a, b with
| None, None => Some None
| Some a, None | None, Some a => Some (Some a)
| Some _, Some _ => None
end.
Definition join (m n o : map) : Prop := forall x, joincell (m x) (n x) = Some (o x).
Definition joins (m n : map) : Prop := exists o, join m n o.
Add Parametric Morphism : join with signature eqmap ==> eqmap ==> eqmap ==> iff as join_morphism.
Definition joincell_split {a b ab c abc} :
joincell a b = Some ab -> joincell ab c = Some abc ->
{ bc | joincell b c = Some bc /\ joincell a bc = Some abc }.
Hint Resolve
join_emptymap_l
join_emptymap_r
joins_emptymap_l
joins_emptymap_r
join_comm
joins_sym.
Definition empty (m : map) : Prop := forall x, m x = None.
Definition nonempty (m : map) : Prop := exists x, m x <> None.
(*+ Predicates over resource maps *)
Definition pred := map -> Prop.
Definition sat (m : map) (P : pred) : Prop := P m.
(* Definition sat (m : map) (P : pred) : Prop := forall n, eqmap m n -> P n. *)
Infix " |= " := sat (at level 40).
Definition emp : pred := fun m => forall n, m n = None.
Definition TT : pred := fun m => True.
Definition FF : pred := fun m => False.
Definition imp (P Q : pred) : Prop := forall m, m |= P -> m |= Q.
Definition sepcon (P Q : pred) : pred :=
fun m => exists m1 m2, join m1 m2 m /\ P m1 /\ Q m2.
Infix "**" := sepcon (at level 30).
Definition pequiv (P Q : pred) := forall m, P m <-> Q m.
Infix " == " := pequiv (at level 50, no associativity).
Definition subheap m o := exists n, join m n o.
Definition precise (R : pred) : Prop := forall o m1 m2,
m1 |= R -> m2 |= R ->
subheap m1 o -> subheap m2 o -> eqmap m1 m2.
Definition mapsto x v : pred := fun m => forall n, m n = if eq_nat_dec x n then Some v else None.
Definition mapsto_ x : pred := fun m => forall n, if eq_nat_dec x n then m n <> None else m n = None.

Lemma precise_join R m1 m2 : precise R -> m1 |= R -> m2 |= R -> joins m1 m2 -> empty m1 /\ empty m2.