Section FOL_SEMANTICS.
Infix "≡" := alpha_equiv : type_scope.
#[local]
Tactic Notation "done" :=
done!.
#[local] Open Scope program_scope.
Context {L : language}.
Definition upd_env {STRUCTURE : isStructureOf L} (y : ivar) (y_value : domain_of_discourse) (env : ivar -> domain_of_discourse) : ivar -> domain_of_discourse :=
fun z : ivar => if eq_dec z y then y_value else env z.
Variable STRUCTURE : isStructureOf L.
Fixpoint interpret_trm (env : ivar -> domain_of_discourse) (t : trm L) {struct t} : domain_of_discourse :=
match t with
| Var_trm x => env x
| Fun_trm f ts => function_interpret f (interpret_trms env ts)
| Con_trm c => constant_interpret c
end
with interpret_trms {n : nat} (env : ivar -> domain_of_discourse) (ts : trms L n) {struct ts} : Vector.t domain_of_discourse n :=
match ts with
| O_trms => []
| S_trms n t ts => interpret_trm env t :: interpret_trms env ts
end.
Fixpoint interpret_frm (env : ivar -> domain_of_discourse) (p : frm L) {struct p} : Prop :=
match p with
| Eqn_frm t1 t2 => interpret_trm env t1 == interpret_trm env t2
| Rel_frm R ts => relation_interpret R (interpret_trms env ts)
| Neg_frm p1 => ~ interpret_frm env p1
| Imp_frm p1 p2 => interpret_frm env p1 -> interpret_frm env p2
| All_frm y p1 => forall y_value : domain_of_discourse, interpret_frm (upd_env y y_value env) p1
end.

Theorem substitution_lemma_frm (env : ivar -> domain_of_discourse) (s : subst L) (p : frm L)
: interpret_frm (interpret_trm env ∘ s) p <-> interpret_frm env (subst_frm s p).