(* 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 *)
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).

(* Specifications: *)
Axiom _env_mapsto_exists: forall {KE: EqDec key}  id sh v, exists rho, _env_mapsto id (pshare_sh sh) v rho.
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.
Axiom _env_get_mapsto': forall {KE: EqDec key}  id (sh: pshare) v rho,
env_get rho id = Some(pfullshare,v) ->
(_env_mapsto id (pshare_sh sh) v * TT)%pred rho.
Axiom _env_mapsto_set: forall {KE: EqDec key} id v,
_env_mapsto id Share.top v (env_set id v empty_env).
Axiom _env_mapsto_set_sh: forall {KE: EqDec key} id (sh: pshare) v,
_env_mapsto id (pshare_sh sh) v (env_set_sh id (Some (sh, v)) empty_env).
Axiom _env_mapsto_get: forall {KE: EqDec key}  id sh v rho,
_env_mapsto id sh v rho
-> exists Pf,
env_get rho id = Some (exist nonunit sh Pf, v).
Axiom _env_mapsto_get_neq: forall {KE: EqDec key}  (id1 id2: key) (sh: Share.t) (v: A) rho,
id1 <> id2 -> _env_mapsto id1 sh v rho -> env_get rho id2 = None.
Axiom _env_mapsto_empty_env: forall {KE: EqDec key}  id v sh, ~(_env_mapsto id sh v empty_env).
Axiom _env_mapsto_splittable: forall {KE: EqDec key}  id v (sh sh1 sh2: pshare) rho,
join sh1 sh2 sh
-> (_env_mapsto id (pshare_sh sh) v rho
<-> (_env_mapsto id (pshare_sh sh1) v * _env_mapsto id (pshare_sh sh2) v)%pred rho).