(* Require Export compcert.lib.Coqlib. *)
From mathcomp.ssreflect Require Import ssreflect ssrbool ssrnat ssrfun eqtype seq fintype finfun.
Set Implicit Arguments.
Set Bullet Behavior "Strict Subproofs".
Set Nested Proofs Allowed.
Definition map_leq {A B} (m1: PTree.t A)(m2: PTree.t B): Prop :=
forall p, m1 ! p -> m2 ! p.
Definition map_empty_def {A} (m1: PMap.t (Z -> option A)):=
m1.1 = fun _ => None.
Definition fun_leq' {A B} (f1: Z -> option A) (f2: Z -> option B): Prop :=
forall p, f1 p -> f2 p.
Definition fun_leq {A B} (o1: option (Z -> option A)) (o2: option (Z -> option B)): Prop :=
match o1, o2 with
| Some f1, Some f2 => fun_leq' f1 f2
| None, None => True
| _, _ => False
end.
Definition option_eq {A B} (a:option A) (b: option B): Prop :=
match a, b with
| Some _ , Some _ => True
| None, None => True
| _, _ => False
end.
Definition bounded_nat_func_aux {A} (f: nat -> option A) hi: Prop :=
(forall p, (p >= hi )%nat -> f p = None).
Definition bounded_nat_func' {A} (f: nat -> option A) hi: Prop :=
(forall p, (p > hi )%nat -> f p = None).
Definition bounded_func' {A} (f: Z -> option A) hi lo: Prop :=
(forall p, (p > hi )%Z -> f p = None) /\
(forall p, (p < lo)%Z -> f p = None).
Definition bounded_func_op {A} (f: option (Z -> option A)) hi lo: Prop :=
match f with
| Some f' => bounded_func' f' hi lo
| None => True
end.
Definition bounded_func {A} (f: Z -> option A): Prop :=
exists hi lo,
bounded_func' f hi lo.
Definition bounded_map {A} (m: PTree.t (Z -> option A)):=
forall p f, m ! p = Some f -> bounded_func f.
Fixpoint strong_tree_leq {A B}
(t1: PTree.t A) (t2: PTree.t B)
(leq: option A -> option B -> Prop):=
match t1, t2 with
| PTree.Leaf, PTree.Leaf => True
| PTree.Node l1 o1 r1, PTree.Node l2 o2 r2 =>
leq o1 o2 /\
strong_tree_leq l1 l2 leq /\
strong_tree_leq r1 r2 leq
| _, _ => False
end.
Definition same_shape {A B} (m1: PTree.t (Z -> option A))(m2: PTree.t (Z -> option B)):=
strong_tree_leq m1 m2 option_eq.
Definition sub_map' {A B} (m1: PTree.t (Z -> option A))(m2: PTree.t (Z -> option B)):=
forall p f1, m1 ! p = Some f1 ->
exists f2, m2 ! p = Some f2 /\ fun_leq' f1 f2.
Definition sub_map {A B} (m1: PTree.t (Z -> option A))(m2: PTree.t (Z -> option B)):=
strong_tree_leq m1 m2 fun_leq.
Definition nat_to_perm (i:nat) :=
(match i with
| 0 => Some None
| 1 => Some (Some Nonempty)
| 2 => Some (Some Readable)
| 3 => Some (Some Writable)
| 4 => Some (Some Freeable)
| _ => None
end)%nat.
Definition perm_to_nat (p: option (option permission)) :=
match p with
| Some (None) => 0
| Some (Some Nonempty) => 1
| Some (Some Readable) => 2
| Some (Some Writable) => 3
| Some (Some Freeable) => 4
| None => 5
end.
Definition nat_to_perm_simpl (i:nat) :=
(match i with
| 0 => None
| 1 => Some Nonempty
| 2 => Some Readable
| 3 => Some Writable
| 4 => Some Freeable
| _ => None
end)%nat.
Definition perm_to_nat_simpl (p: option permission) :=
match p with
| None => 0
| Some Nonempty => 1
| Some Readable => 2
| Some Writable => 3
| Some Freeable => 4
end.

Lemma finite_sub_maps:
forall m2,
@bounded_map permission m2 ->
konig.finite
(fun m1 => @sub_map (option permission) permission m1 m2).