Definition io_specs :=
[(_getchar, getchar_spec); (_putchar, putchar_spec)].
Definition ext_link := ext_link_prog prog.
(* Should we really need a concrete user program in order to build enough of an external_specification for the juicy_dry proof? *)
Definition io_ext_spec
:=
add_funspecs_rec
ext_link
(ok_void_spec IO_itree).(@OK_ty)
(ok_void_spec IO_itree).(@OK_spec)
io_specs.
Definition getchar_pre (m : mem) (k : int -> IO_itree) (z : IO_itree) :=
(z = (r <- read;; k r))%eq_utt.
Definition getchar_post (m0 m : mem) r (k : int -> IO_itree) (z : IO_itree) :=
m0 = m /\ - two_p 7 <= Int.signed r <= two_p 7 - 1 /\ z = k r.
Definition putchar_pre (m : mem) c (k : IO_itree) (z : IO_itree) :=
(z = (write c;; k))%eq_utt.
Definition putchar_post (m0 m : mem) r (c : int) (k : IO_itree) (z : IO_itree) :=
m0 = m /\ r = c /\ z = k.
Program Definition io_dry_spec : external_specification mem external_function IO_itree.

(* Specifications: *)
Lemma nth_nil : forall {A} n (d : A), nth n nil d = d.
Lemma ghost_join_nth : forall (a b c : ghost) n, join a b c ->
join (nth n a None) (nth n b None) (nth n c None).
(* up *)
Lemma has_ext_join : forall {Z} phi1 phi2 phi3 (z1 z2 : Z) (Hext : nth O (ghost_of phi1) None = Some (ext_ghost z1, NoneP))
(Hj : join phi1 phi2 phi3) (Hrest : joins (ghost_of phi3) [Some (ext_ref z2, NoneP)]),
z1 = z2 /\ nth O (ghost_of phi3) None = Some (ext_ghost z1, NoneP).
Lemma rebuild_same : forall jm,
juicy_mem_lemmas.rebuild_juicy_mem_fmap jm (m_dry jm) = resource_at (m_phi jm).
Lemma change_ext : forall {Z} (a a' z : Z) (b c : ghost),
join [Some (ext_ghost a, NoneP)] b c ->
joins c [Some (ext_ref z, NoneP)] ->
join [Some (ext_ghost a', NoneP)] b (Some (ext_ghost a', NoneP) :: tl c).
Lemma change_has_ext : forall {Z} (a a' : Z) r H, has_ext a r ->
has_ext a' (set_ghost r [Some (ext_ghost a', NoneP)] H).
(* up *)
Lemma ext_ref_join : forall {Z} (z : Z), join (ext_ghost z) (ext_ref z) (ext_both z).
Lemma age_rejoin : forall {Z} w1 w2 w w' (a a' z : Z) H (J : join w1 w2 w)
(Hc : joins (ghost_of w) [Some (ext_ref z, NoneP)])
(Hg1 : ghost_of w1 = [Some (ext_ghost a, NoneP)])
(Hl' : (level w' <= level w)%nat)
(Hr' : forall l, w' @ l = resource_fmap (approx (level w')) (approx (level w')) (w @ l))
(Hg' : ghost_of w' = Some (ext_ghost a', NoneP) :: own.ghost_approx (level w') (tl (ghost_of w))),
join (age_to.age_to (level w') (set_ghost w1 [Some (ext_ghost a', NoneP)] H)) (age_to.age_to (level w') w2) w'.
Theorem juicy_dry_specs : juicy_dry_ext_spec _ io_ext_spec io_dry_spec dessicate.
Instance mem_evolve_refl : Reflexive mem_evolve.
Lemma dry_spec_mem : ext_spec_mem_evolve _ io_dry_spec.