Module Mem <: MEM.
Definition perm_order' (po: option permission) (p: permission) :=
match po with
| Some p' => perm_order p' p
| None => False
end.
Definition perm_order'' (po1 po2: option permission) :=
match po1, po2 with
| Some p1, Some p2 => perm_order p1 p2
| _, None => True
| None, Some _ => False
end.
Record mem' : Type := mkmem {
mem_contents: PMap.t (ZMap.t memval);  (**r [block -> offset -> memval] *)
mem_access: PMap.t (Z -> perm_kind -> option permission);
(**r [block -> offset -> kind -> option permission] *)
nextblock: block;
access_max:
forall b ofs, perm_order'' (mem_access#b ofs Max) (mem_access#b ofs Cur);
nextblock_noaccess:
forall b ofs k, ~(Plt b nextblock) -> mem_access#b ofs k = None;
contents_default:
forall b, fst mem_contents#b = Undef
}.
Definition mem := mem'.
(** * Validity of blocks and accesses *)
(** A block address is valid if it was previously allocated. It remains valid even after being freed. *)
Definition valid_block (m: mem) (b: block) := Plt b (nextblock m).
Local Hint Resolve valid_not_valid_diff: mem.
(** Permissions *)
Definition perm (m: mem) (b: block) (ofs: Z) (k: perm_kind) (p: permission) : Prop :=
perm_order' (m.(mem_access)#b ofs k) p.
Local Hint Resolve perm_implies: mem.
Local Hint Resolve perm_cur perm_max: mem.
Local Hint Resolve perm_valid_block: mem.
Remark perm_order_dec:
forall p1 p2, {perm_order p1 p2} + {~perm_order p1 p2}.
Local Hint Resolve range_perm_implies range_perm_cur range_perm_max: mem.
Local Hint Resolve valid_access_implies: mem.
Local Hint Resolve valid_access_valid_block: mem.

Lemma valid_access_perm:
forall m chunk b ofs k p,
valid_access m chunk b ofs p ->
perm m b ofs k p.