(*************************************************************************)
(** * Free variables *)
(*************************************************************************)
(** The function [fv], defined below, calculates the set of free variables in an expression.  Because we are using a locally nameless representation, where bound variables are represented as indices, any name we see is a free variable of a term.  In particular, this makes the [abs] case simple. *)
Fixpoint fv (e : exp) {struct e} : atoms :=
match e with
| bvar i => empty
| fvar x => singleton x
| abs t e1 => fv e1
| app e1 e2 => (fv e1) `union` (fv e2)
end.
(** The type [atoms] represents a finite set of elements of type [atom].  The notation for infix union is defined in the Metatheory library. *)

(* Specifications: *)
(* Demo [f_equal]  The tactic [f_equal] converts a goal of the form [f e1 = f e1'] in to one of the form [e1 = e1'], and similarly for [f e1 e2 = f e1' e2'], etc. *)
Lemma f_equal_demo : forall e1 e2, e1 = e2 -> fv e1 = fv e2.
(* Demo [fsetdec]  The tactic [fsetdec] solves a certain class of propositions involving finite sets. See the documentation in [FSetWeakDecide] for a full specification. *)
Lemma fsetdec_demo : forall (x :atom) (S : atoms),
x `in` (singleton x `union` S).