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.

Lemma fvs_is_free_in_frms (ps : ensemble (frm L))
: forall z, z \in fvs_frms ps <-> (exists p, p \in ps /\ is_free_in_frm z p = true).