Module unique := fc_unique wf subst.
Set Bullet Behavior "Strict Subproofs".
Set Implicit Arguments.
(* This version is just for "head reduction." *)
intros.
unfold open_tm_wrt_tm. simpl. auto.
Qed.
intros.
unfold open_tm_wrt_co. simpl. auto.
Qed.
(* Helper tactic for below. Solves lc_tm goals using hypotheses from the annotated language. Perhaps it is useful elsewhere? *)
Ltac lc_erase_hyp :=
match goal with
| H : AnnTyping ?G ?a ?A0 |- lc_tm (erase_tm ?a) => eapply lc_erase; apply (AnnTyping_lc H)
| H : AnnTyping ?G ?a ?A0 |- lc_tm ?a => apply (AnnTyping_lc1 H)
| H : lc_tm ?a |- lc_tm (erase ?a) => eapply lc_erase; eauto
| H : lc_tm (a_Abs ?r ?a ?b) |- lc_tm ?c => apply lc_erase in H; simpl in H; auto
| H : lc_tm (a_CAbs ?a ?b) |- lc_tm ?c => apply lc_erase in H; simpl in H; auto
end.
Ltac do_rho :=
match goal with
H : ∀ x : atom, x `notin` ?L → RhoCheck Irrel x (erase_tm (open_tm_wrt_tm ?b (a_Var_f x))) |-
?x `notin` fv_tm_tm_tm (open_tm_wrt_tm (erase ?b) (a_Var_f ?x)) =>
let h := fresh in
let F := fresh in
assert (F : x `notin` L); auto;
move: (H x F) => h; inversion h; subst;
replace (a_Var_f x) with (erase (a_Var_f x)); auto;
rewrite open_tm_erase_tm; auto
end.
(* A specialized version of eauto that only uses the most common lc lemmas to cut down the search space. *)
Ltac eauto_lc := simpl; eauto using AnnTyping_lc1, Value_lc,
AnnDefEq_lc3, AnnPropWff_lc.
(* We need to know that the term type checks.  But if it does, our annotated operational semantics corresponds with parallel reduction. *)

Lemma preservation : forall G a A, AnnTyping G a A -> forall a', head_reduction G a a' -> AnnTyping G a' A.