Section SpecsCorrect.
Context `{ThreadsConfigurationOps}.
Definition user_trace (ot ot' : ostrace) : trace :=
trace_of_ostrace (strip_common_prefix IOEvent_eq ot ot').
Definition trace_itree_match (z0 z : IO_itree) (ot ot' : ostrace) :=
(* Compute the OS-generated trace of newly added events *)
let ot_new := strip_common_prefix IOEvent_eq ot ot' in
(* Filter out the user-invisible events *)
let t := trace_of_ostrace ot_new in
(* The new itree 'consumed' the OS-generated trace *)
consume_trace z0 z t.
Variable block_to_addr : block -> Z.
Definition mem_to_flatmem (f : flatmem) (m : mem) (b : block) (ofs len : Z) : flatmem :=
let contents := getN (Z.to_nat len) ofs (m.(mem_contents) !! b) in
let addr := block_to_addr b + ofs in
FlatMem.setN contents addr f.
Program Definition flatmem_to_mem (f : flatmem) (m : mem) (b : block) (ofs len : Z) : mem :=
let (cont, acc, nxt, amax, nxt_no, _) := m in
let addr := block_to_addr b + ofs in
let bytes := FlatMem.getN (Z.to_nat len) addr f in
let contents := setN bytes ofs (cont !! b) in
mkmem (PMap.set b contents cont) acc nxt amax nxt_no _.
Next Obligation.
cbn; intros; destruct (Pos.eq_dec b b0) eqn:?; subst.
- rewrite PMap.gss, setN_default; auto.
- rewrite PMap.gso; auto.
Defined.
Record R_sys_getc_correct k z m st st' ret := {
(* New itree is old k applied to result, or same as old itree if nothing to read *)
getc_z' := if 0 <=? Int.signed ret then k (Byte.repr (Int.signed ret)) else z;
(* Post condition holds on new state, itree, and result *)
getc_post_ok : getchar_post' m m ret (k, z) getc_z';
(* The itrees and OS traces agree on the external events *)
getc_itree_trace_ok : trace_itree_match z getc_z' st.(io_log) st'.(io_log);
(* The new trace is valid *)
getc_trace_ok : valid_trace st';
(* The memory is unchanged *)
getc_mem_ok : st.(HP) = st'.(HP)
}.
(* Initial trace is valid *)
(* Pre condition holds *)
(* sys_getc returns some state *)
Record R_sys_putc_correct c k z m st st' ret := {
(* New itree is old k, or same as old itree if send failed *)
putc_z' := if 0 <=? Int.signed ret then k else z;
(* Post condition holds on new state, itree, and result *)
putc_post_ok : putchar_post m m ret (c, k) putc_z';
(* The itrees and OS traces agree on the external events *)
putc_itree_trace_ok : trace_itree_match z putc_z' st.(io_log) st'.(io_log);
(* The new trace is valid *)
(* TODO: have to define valid trace condition for putc *)
putc_trace_ok : valid_trace st';
(* The memory is unchanged *)
putc_mem_ok : st.(HP) = st'.(HP)
}.

Lemma sys_putc_correct c k z m st st' :
valid_trace st ->
putchar_pre m (c, k) z ->
get_sys_arg1 st = functional_base.Vubyte c ->
sys_putc_spec st = Some st' ->
exists ret,
get_sys_ret st' = Vint ret /\
R_sys_putc_correct c k z m st st' ret.