Section EQUATIONS. (* Reference: "https://github.com/princeton-vl/CoqGym/blob/master/coq_projects/goedel/folLogic3.v" *)
Fixpoint pairwise_equal {n : nat} (Gamma : ensemble (frm L)) {struct n} : trms L n -> trms L n -> Prop :=
match n with
| O => fun ts => fun ts' => True
| S n' => fun ts => fun ts' => Gamma \proves (Eqn_frm (head ts) (head ts')) /\ pairwise_equal (n := n') Gamma (tail ts) (tail ts')
end.
Definition trms_map : forall n, trms L n -> trms L n -> subst L :=
nat_rec (fun n => trms L n -> trms L n -> ivar -> trm L) (fun _ => fun _ => fun z => Var_trm z) (fun n => fun ACC => fun ts => fun ts' => fun z => if eq_dec z (n + n) then head ts else if eq_dec z (S (n + n)) then head ts' else ACC (tail ts) (tail ts') z).
#[local] Opaque le_lt_dec.
#[local] Tactic Notation "des" :=
unfold eq_dec, ivar_hasEqDec; lazymatch goal with [ |- context[ Nat.eq_dec ?P ?Q ] ] => destruct (Nat.eq_dec P Q); try lia | [ |- context[ le_lt_dec ?P ?Q ] ] => destruct (le_lt_dec P Q); try lia end.

Lemma proves_eqn_trm (t : trm L) (lhs : trm L) (rhs : trm L) (Gamma : ensemble (frm L)) (y : ivar)
(PROVE : Gamma \proves Eqn_frm lhs rhs)
: Gamma \proves Eqn_frm (subst_trm (one_subst y lhs) t) (subst_trm (one_subst y rhs) t)
with proves_eqn_trms n (ts : trms L n) (lhs : trm L) (rhs : trm L) (Gamma : ensemble (frm L)) (y : ivar)
(PROVE : Gamma \proves Eqn_frm lhs rhs)
: pairwise_equal Gamma (subst_trms (one_subst y lhs) ts) (subst_trms (one_subst y rhs) ts).