Require Export VST.veric.base.
Local Open Scope pred.
Notation ghost_approx m := (ghost_fmap (approx (level m)) (approx (level m))).
(* Ownership construction based on "Iris from the ground up", Jung et al. *)
Program Definition ghost_is g: pred rmap :=
fun m => ghost_of m = ghost_approx m g.
Next Obligation.
intros ???? Hg.
rewrite (age1_ghost_of _ _ H), Hg.
pose proof (age_level _ _ H).
rewrite ghost_fmap_fmap, approx_oo_approx', approx'_oo_approx by omega; eauto.
Qed.
Definition Own g: pred rmap := allp noat && ghost_is g.

(* Specifications: *)
Lemma Own_op: forall a b c, join a b c -> Own c = Own a * Own b.
Fixpoint make_join (a c : ghost) : ghost :=
match a, c with
| nil, _ => c
| _, nil => nil
| None :: a', x :: c' => x :: make_join a' c'
| _ :: a', None :: c' => None :: make_join a' c'
| Some (ga, pa) :: a', Some (gc, _) :: c' => Some (gc, pa) :: make_join a' c'
end.
Lemma make_join_nil : forall a, make_join a nil = nil.
Lemma make_join_nil_cons : forall o a c, make_join (o :: a) (None :: c) = None :: make_join a c.
Lemma ghost_joins_approx: forall n a c,
joins (ghost_fmap (approx n) (approx n) a) (ghost_fmap (approx n) (approx n) c) ->
let c' := make_join a c in
joins (ghost_fmap (approx (S n)) (approx (S n)) a) (ghost_fmap (approx (S n)) (approx (S n)) c') /\
forall b, joins b (ghost_fmap (approx (S n)) (approx (S n)) c') ->
joins (ghost_fmap (approx n) (approx n) b) (ghost_fmap (approx n) (approx n) c).