Proof with try (left; right; econstructor; eauto; fail).
intros until S'. destruct S; simpl.
(* State *)
destruct s; myinv...
(* skip *)
destruct k; myinv...
(* break *)
destruct k; myinv...
(* continue *)
destruct k; myinv...
(* goto *)
destruct p as [s' k']. myinv...
(* ExprState *)
destruct (is_val r) as [[v ty]|] eqn:?.
(* expression is a value *)
rewrite (is_val_inv _ _ _ Heqo).
destruct k; myinv...
(* expression reduces *)
intros. exploit list_in_map_inv; eauto. intros [[C rd] [A B]].
generalize (step_expr_sound e w r RV m). unfold reducts_ok. intros [P Q].
exploit P; eauto. intros [a' [k' [CTX [EQ RD]]]].
unfold expr_final_state in A. simpl in A.
destruct k'; destruct rd; inv A; simpl in RD; try contradiction.
(* lred *)
left; left; apply step_lred; auto.
(* stuck lred *)
exploit not_imm_safe_t; eauto. intros [R | R]; eauto.
(* rred *)
destruct RD. left; left; apply step_rred; auto.
(* callred *)
destruct RD; subst m'. left; left; apply step_call; eauto.
(* stuck rred *)
exploit not_imm_safe_t; eauto. intros [R | R]; eauto.
(* callstate *)
destruct fd; myinv.
(* internal *)
destruct (do_alloc_variables empty_env m (fn_params f ++ fn_vars f)) as [e m1] eqn:?.
myinv. left; right; apply step_internal_function with m1. auto.
change e with (fst (e,m1)). change m1 with (snd (e,m1)) at 2. rewrite <- Heqp.
apply do_alloc_variables_sound. eapply sem_bind_parameters_sound; eauto.
(* external *)
destruct p as [[[w' tr] v] m']. myinv. left; right; constructor.
eapply do_ef_external_sound; eauto.
(* returnstate *)
destruct k; myinv...
(* stuckstate *)
contradiction.
Qed.
Remark estep_not_val:
forall f a k e m t S, estep ge (ExprState f a k e m) t S -> is_val a = None.

(* Specifications: *)
Theorem do_step_complete:
forall w S t S' w',
possible_trace w t w' -> Csem.step ge S t S' -> exists rule, In (TR rule t S') (do_step w S).