Section FOL_SYNTAX. (* Reference: "https://github.com/ernius/formalmetatheory-stoughton" *)
#[local] Hint Unfold compose : simplication_hints.
#[local] Open Scope program_scope.
Definition renaming : Set :=
ivar -> ivar.
Definition subst (L : language) : Set :=
ivar -> trm L.
Context {L : language}.
Fixpoint fvs_trm (t : trm L) : list ivar :=
match t with
| Var_trm x => [x]
| Fun_trm f ts => fvs_trms ts
| Con_trm c => []
end
with fvs_trms {n : nat} (ts : trms L n) : list ivar :=
match ts with
| O_trms => []
| S_trms n t ts => fvs_trm t ++ fvs_trms ts
end.
Fixpoint fvs_frm (p : frm L) : list ivar :=
match p with
| Rel_frm r ts => fvs_trms ts
| Eqn_frm t1 t2 => fvs_trm t1 ++ fvs_trm t2
| Neg_frm p1 => fvs_frm p1
| Imp_frm p1 p2 => fvs_frm p1 ++ fvs_frm p2
| All_frm y p1 => List.remove eq_dec y (fvs_frm p1)
end.
#[local] Hint Rewrite fv_is_free_in_trm fv_is_free_in_trms : simplication_hints.
#[local] Hint Rewrite fv_is_free_in_frm : simplication_hints.
Definition is_not_free_in_trm (x : ivar) (t : trm L) : Prop :=
is_free_in_trm x t = false.
Definition is_not_free_in_trms {n : nat} (x : ivar) (ts : trms L n) : Prop :=
is_free_in_trms x ts = false.
Definition is_not_free_in_frm (x : ivar) (p : frm L) : Prop :=
is_free_in_frm x p = false.
#[local] Hint Unfold is_not_free_in_frm is_free_in_trms is_not_free_in_frm : simplication_hints.
Definition fvs_frms (ps : ensemble (frm L)) : ensemble ivar :=
ps >>= E.fromList ∘ fvs_frm.
#[local] Hint Rewrite fvs_is_free_in_frms : simplication_hints.
Definition is_not_free_in_frms (x : ivar) (ps : ensemble (frm L)) : Prop :=
forall p, p \in ps -> is_free_in_frm x p = false.
#[local] Hint Unfold is_not_free_in_frms : simplication_hints.
Definition last_ivar_trm (t : trm L) : ivar :=
maxs (fvs_trm t).
Fixpoint last_ivar_trms {n : nat} (ts : trms L n) : ivar :=
match ts with
| O_trms => 0
| S_trms n t ts => max (last_ivar_trm t) (last_ivar_trms (n := n) ts)
end.
Definition last_ivar_frm (p : frm L) : ivar :=
maxs (fvs_frm p).
#[local] Hint Unfold last_ivar_trm last_ivar_frm : simplication_hints.
#[local] Hint Rewrite <- last_ivar_trms_eq_maxs_fvs : simplication_hints.
Definition chi_frm (s : subst L) (p : frm L) : ivar :=
1 + maxs (List.map (last_ivar_trm ∘ s) (fvs_frm p)).

Lemma chi_frm_not_free (s : subst L) (p : frm L) (x : ivar)
(FREE : is_free_in_frm x p = true)
: is_free_in_trm (chi_frm s p) (s x) = false.