Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Module Event.
Record t : Type :=
mk { pre_mem  : mem
; post_mem : mem
; args : list val
; rv   : option val }.
End Event.
Module TraceSemantics. Section trace_semantics.
Context {G C Z : Type}.
Variable z_init : Z.
Variable sem : @CoopCoreSem G C.
Variable spec : ext_spec Z.
Definition yielded c :=
(exists ef sig args, at_external sem c = Some (ef, sig, args))
\/ exists rv, halted sem c = Some rv.
Inductive step
: G -> (Z*list Event.t*C) -> mem -> (Z*list Event.t*C) -> mem -> Prop :=
| trace_step :
forall ge tr z c m c' m',
corestep sem ge c m c' m' ->
step ge (z,tr,c) m (z,tr,c') m'
| trace_extern :
forall ge tr z c m z' c' m' ef sig args rv x,
at_external sem c = Some (ef, sig, args) ->
Mem.unchanged_on (fun b ofs => REACH m (getBlocks args) b=false) m m' ->
mem_forward m m' ->
ext_spec_pre spec ef x (sig_args sig) args z m ->
ext_spec_post spec ef x (sig_res sig) (Some rv) z' m' ->
after_external sem (Some rv) c = Some c' ->
step ge (z,tr,c) m (z',Event.mk m m' args (Some rv) :: tr,c') m'.
Definition initial_core (ge : G) (v : val) (vs : list val)
: option (Z*list Event.t*C) :=
match initial_core sem ge v vs with
| Some c => Some (z_init, nil, c)
| None => None
end.
Definition halted (c : Z*list Event.t*C) := halted sem (snd c).
Program Definition coresem : CoreSemantics G (Z*list Event.t*C) mem :=
@Build_CoreSemantics G (Z*list Event.t*C) mem
initial_core
(fun _ => None)
(fun _ _ => None)
halted
step
_ _ _ _.
Next Obligation.
inv H; unfold halted; simpl.
solve[apply corestep_not_halted in H9; auto].
solve[destruct (at_external_halted_excl sem c0); try congruence; auto].
Qed.
Program Definition coopsem : CoopCoreSem G (Z*list Event.t*C) :=
@Build_CoopCoreSem G (Z*list Event.t*C) coresem _.
Next Obligation.
destruct CS; auto.
solve[apply corestep_fwd in H; auto].
Qed.

Lemma corestepN_geq ge c m c' m' c'' m'' z tr z' tr' n1 n2 :
corestep_fun sem ->
corestepN sem ge n1 c m c' m' ->
corestepN coopsem ge n2 (z,tr,c) m (z',tr',c'') m'' ->
(n1 >= n2)%nat ->
z=z' /\ tr=tr'.