Section ENVSEC.
Context {key: Type}{A: Type}.
Instance JA: Join A := Join_equiv A. (* It's a feature, not a bug, that this Instance is not visible as an Instance
outside the Section *)
Parameter env_get: forall (rho: env key A) (id: key), option (pshare * A).
Parameter env_set_sh: forall {KE: EqDec key} (id: key) (v: option (pshare * A)) (rho: env key A), env key A.
Definition env_set  {KE: EqDec key} (id: key) (v: A) (rho: env key A) : env key A :=
env_set_sh id (Some (pfullshare, v)) rho.
Definition finite_idfun (f: key -> option (pshare * A)) :=
exists l, forall a, ~In a l -> f a = None.
Parameter mk_env:  forall (f: key -> option (pshare * A)), finite_idfun f -> env key A.
(* Arguments mk_env. *)
Parameter empty_env : env key A.
(* SEPARATION ALGEBRAS *)
(* We use the Section to hide these instances, because  variables-as-resources clients will want Join_env, but global-variables users will want Join_equiv. Only the variables-as-resources clients should add these instances, which is done in the Module EnvSA,  below *)
Instance Join_env: Join (env key A) :=
fun (rho1 rho2 rho3: env key A) => join (env_get rho1) (env_get rho2) (env_get rho3).
Parameter Perm_env: forall {PA: Perm_alg A}, Perm_alg (env key A).  Existing Instance Perm_env.
Instance Sep_env {SA: Sep_alg A}: Sep_alg (env key A).
refine (mkSep Join_env (fun _ => empty_env) _ _).
repeat intro; rewrite env_get_empty; constructor.
auto.
Defined.
Instance Sing_env  {SA: Sep_alg A} : Sing_alg (env key A).
refine (mkSing empty_env _). reflexivity.
Defined.
Parameter Canc_env: forall {PA: Perm_alg A}{CA: Canc_alg A}, Canc_alg (env key A). Existing Instance Canc_env.
Parameter Disj_env: forall {PA: Perm_alg A}{DA: Disj_alg A}, Disj_alg (env key A).   Existing Instance Disj_env.
Parameter Cross_env : Cross_alg (env key A).  Existing Instance Cross_env.
(* env_mapsto and the lemmas about it are in a Separation Logic, not just a separation algebra. We have two style of separation logic (direct and ageable), and this module Env is usable with either kind.  Thus, we build primitives whose names start with _ to avoid polluting the namespace; then we reveal them at appropriate types in EnvSL and EnvASL, below. *)
(* ENV_MAPSTO *)
Parameter _env_mapsto: forall {KE: EqDec key}  (id: key) (sh: Share.t) (v: A), pred (env key A).

Axiom _env_get_mapsto: forall {KE: EqDec key}  id v rho,
(exists sh, env_get rho id = Some (sh,v)) =
(exp (fun sh => _env_mapsto id sh v) * TT)%pred rho.