Section IO_Dry.
Definition bytes_to_memvals li := concat (map (fun i => encode_val Mint8unsigned (Vubyte i)) li).
Context {E : Type -> Type} {IO_E : @IO_event nat -< E}.
Definition getchars_pre (m : mem) (witness : share * val * Z * (list byte -> IO_itree)) (z : IO_itree) :=
let '(sh, buf, len, k) := witness in (sutt eq (r <- read_list stdin (Z.to_nat len);; k r) z) /\
match buf with Vptr b ofs =>
Mem.range_perm m b (Ptrofs.unsigned ofs) (Ptrofs.unsigned ofs + Z.max 0 len) Memtype.Cur Memtype.Writable
| _ => False end.
Definition getchars_post (m0 m : mem) r (witness : share * val * Z * (list byte -> IO_itree)) (z : @IO_itree E) :=
let '(sh, buf, len, k) := witness in r = Int.repr len /\
exists msg, Zlength msg = len /\ z = k msg /\
match buf with Vptr b ofs => exists m', Mem.storebytes m0 b (Ptrofs.unsigned ofs) (bytes_to_memvals msg) = Some m' /\
mem_equiv m m'
| _ => False end.
Definition putchars_pre (m : mem) (witness : share * val * list byte * Z * list val * IO_itree) (z : IO_itree) :=
let '(sh, buf, msg, _, _, k) := witness in (sutt eq (write_list stdout msg;; k) z) /\
match buf with Vptr b ofs =>
Mem.loadbytes m b (Ptrofs.unsigned ofs) (Zlength msg) =
Some (bytes_to_memvals msg)
| _ => False end.
Definition putchars_post (m0 m : mem) r (witness : share * val * list byte * Z * list val * IO_itree) (z : @IO_itree E) :=
let '(sh, buf, msg, _, _, k) := witness in m0 = m /\ r = Int.repr (Zlength msg) /\ z = k.
Context {CS : compspecs} (ext_link : String.string -> ident).
Instance Espec : OracleKind := IO_Espec ext_link.
Definition io_ext_spec := OK_spec.
Program Definition io_dry_spec : external_specification mem external_function (@IO_itree E).
Instance mem_evolve_refl : Reflexive mem_evolve.

Lemma dry_spec_mem : ext_spec_mem_evolve _ io_dry_spec.