(* -------------------------------
   Find a better place for these tactics
*)
Ltac expand sub_tm tm :=
  match tm with
  | (a_Abs ?rho (_ ?A1) (_ ?b)) =>
    replace (a_Abs rho (sub_tm A1) (sub_tm b)) with (sub_tm (a_Abs rho A1 b)); auto
  | (a_Pi ?rho (_ ?A1) (_ ?B1)) =>
    replace (a_Pi rho (sub_tm A1) (sub_tm B1)) with (sub_tm (a_Pi rho A1 B1)); auto
  | (a_CAbs (?sc ?phi) (_ ?B)) =>
    replace (a_CAbs (sc phi) (sub_tm B)) with (sub_tm (a_CAbs phi B)); auto
  | (a_CPi (?sc ?phi) (_ ?B)) =>
    replace (a_CPi (sc phi) (sub_tm B)) with (sub_tm (a_CPi phi B)); auto

  | a_Star => replace a_Star with (sub_tm a_Star); auto

  | _ => idtac
  end.Ltac expand_constraint sub_tm sub_constraint constraint :=
  match constraint with
  | (Eq (_ _ _ ?a) (_ _ _  ?b) (_ _ _ ?A)) =>
    replace (Eq (sub_tm a) (sub_tm b) (sub_tm A)) with
    (sub_constraint (Eq a b A)); auto
  | _ => idtac
  end.Ltac un_subst_tm :=
   match goal with
   | [ |- context [tm_subst_tm_tm ?g ?c _] ] =>
     match goal with
     | [ |- Typing _ ?a ?A ] => expand (tm_subst_tm_tm g c) a; expand (tm_subst_tm_tm g c) A
     | [ |- DefEq _ _ ?a ?b ] => expand (tm_subst_tm_tm g c) a; expand (tm_subst_tm_tm g c) b
     | [ |- PropWff ?phi ] => expand_constraint (tm_subst_tm_tm g c) (tm_subst_tm_constraint g c) phi
     end
   | [ |- context [co_subst_co_tm ?g ?c _] ] =>
     match goal with
     | [ |- Typing _ ?a ?A ] => expand (co_subst_co_tm g c) a; expand (co_subst_co_tm g c) A
     | [ |- DefEq _ _ ?a ?b ] => expand (co_subst_co_tm g c) a; expand (co_subst_co_tm g c) b
     | [ |- PropWff ?phi ] => expand_constraint (co_subst_co_tm g c) (co_subst_co_constraint g c) phi
     end
   end.

(* Specifications: *)
Lemma Typing_regularity : forall e A G, Typing G e A -> Typing G A a_Star.
Lemma refl_iso: forall G D phi, PropWff G phi -> Iso G D phi phi.
Lemma sym_iso: forall G D phi1 phi2, Iso G D phi1 phi2 -> Iso G D phi2 phi1.
Lemma invert_a_App_Rel : forall G a b C, Typing G (a_App a Rel b) C -> exists A B, Typing G a (a_Pi Rel A B) /\ Typing G b A /\ DefEq G (dom G) C (open_tm_wrt_tm B b) a_Star.
Lemma invert_a_App_Irrel : forall G a b C, Typing G (a_App a Irrel b) C -> exists A B b0, Typing G a (a_Pi Irrel A B) /\ Typing G b0 A /\ DefEq G (dom G) C (open_tm_wrt_tm B b0) a_Star.
Lemma invert_a_CApp : forall G a g A, Typing G (a_CApp a g) A -> g = g_Triv /\ exists a1 b1 A1 B, Typing G a (a_CPi (Eq a1 b1 A1) B) /\ DefEq G (dom G) a1 b1 A1 /\ DefEq G (dom G) A (open_tm_wrt_co B g_Triv) a_Star.
Lemma context_tm_binding_defeq: forall D (G1 G2: context) A x, Ctx G1 -> Ctx G2 -> context_DefEq D G1 G2 -> binds x (Tm A) G1 -> exists A', (binds x (Tm A') G2) /\ DefEq G2 D A A' a_Star.
Lemma context_co_binding_defeq: forall D (G1 G2: context) phi1 c, Ctx G1 -> Ctx G2 -> context_DefEq D G1 G2 -> binds c (Co phi1) G1 -> exists phi2, (binds c (Co phi2) G2) /\ Iso G2 D phi1 phi2.
Lemma same_dom : forall D (G1 : context) G2, context_DefEq D G1 G2 -> (@dom ett_ott.sort G1) = (@dom ett_ott.sort G2).
Lemma context_DefEq_weaken_available : forall D G1 G2, context_DefEq D G1 G2 -> context_DefEq (dom G1) G1 G2.
Lemma context_DefEq_mutual: (forall G1 a A, Typing G1 a A -> forall D G2, Ctx G2 -> context_DefEq D G1 G2 -> Typing G2 a A) /\ (forall G1 phi, PropWff G1 phi -> forall D G2, Ctx G2 -> context_DefEq D G1 G2 -> PropWff G2 phi) /\ (forall G1 D p1 p2, Iso G1 D p1 p2 -> forall G2, Ctx G2 -> context_DefEq D G1 G2 -> Iso G2 D p1 p2) /\ (forall G1 D1 A B T, DefEq G1 D1 A B T -> forall G2, Ctx G2 -> context_DefEq D1 G1 G2 -> DefEq G2 D1 A B T) /\ (forall G1 , Ctx G1 -> forall G2 D x A, Ctx G2 -> context_DefEq D G1 G2 -> binds x (Tm A) G1 -> Typing G2 A a_Star).
Lemma context_DefEq_typing: forall G1 a A, Typing G1 a A -> forall D G2, Ctx G2 -> context_DefEq D G1 G2 -> Typing G2 a A.
Lemma refl_context_defeq: forall G D, Ctx G -> context_DefEq D G G.
Lemma co_subst_co_tm_var_eq : forall a g c, lc_co g -> erased_tm a -> co_subst_co_tm g_Triv c a = co_subst_co_tm g c a.
Lemma DefEqIso_regularity : (forall G0 a A, Typing G0 a A -> True ) /\ (forall G0 phi, PropWff G0 phi -> True ) /\ (forall G D p1 p2, Iso G D p1 p2 -> PropWff G p1 /\ PropWff G p2) /\ (forall G D A B T, DefEq G D A B T -> Typing G A T /\ Typing G B T) /\ (forall G0, Ctx G0 -> True).
Lemma DefEq_regularity : forall G D A B T, DefEq G D A B T -> PropWff G (Eq A B T).
Lemma Iso_regularity : forall G D phi1 phi2, Iso G D phi1 phi2 -> PropWff G phi1 /\ PropWff G phi2.
Lemma PropWff_regularity : forall G A B T, PropWff G (Eq A B T) -> Typing G A T /\ Typing G B T.
Lemma DefEq_conv : forall G D a b A B, DefEq G D a b A -> DefEq G (dom G) A B a_Star -> DefEq G D a b B.
Lemma trans_iso : forall G D phi1 phi2 phi3, Iso G D phi1 phi2 -> Iso G D phi2 phi3 -> Iso G D phi1 phi3.
Lemma iso_cong : forall G D A A' B B' T T', DefEq G D A A' T -> DefEq G D B B' T -> DefEq G D T T' a_Star -> Iso G D (Eq A B T) (Eq A' B' T').