(***********************************************************************)
(** * Connecting "freshening" *)
(***********************************************************************)
(** The abstract machine uses the nominal [swap] operation to make sure that the variables in abstractions are "fresh".  To be able prove that this machine implements the step relation for LN terms, we need to connect this operation to a LN version of "freshening".  The [swap_spec] lemma below states that connection. If a variable [y] is "fresh", then substituting with it (in the LN representation) is the same as swapping with it (in the nominal representation).  << Lemma swap_spec : forall  n w y, y `notin` fv_exp (nom_to_exp n) -> w <> y -> [w ~> var_f y] (nom_to_exp n) = nom_to_exp (swap w y n). >>  *)
(** *** Exercise [close_exp_wrt_exp_freshen] *)

(* Specifications: *)
(** The [swap_spec] proof depends on the following auxiliary lemma about the close operation --- that we can equivalently rename the atom that we are closing with. *)
(* LATER *)
(* SCW: Make LNgen generate this? *)
(* /LATER *)
Lemma close_exp_wrt_exp_freshen : forall x y e,
y `notin` fv_exp e ->
close_exp_wrt_exp x e =
close_exp_wrt_exp y ([x ~> var_f y] e).
(** One difficulty of [swap_spec] is that we need to use the induction not on direct subterms, but on those that have had a swapping applied to them. Swapping preserves the size of a nominal term, so we can prove this result by induction on [m], a bound on the size of the term.  The difficulty in this proof comes from the [n_abs] case. In this case, the term is is of the form [n_abs x t] for some binding variable [x]. We don't know much about [x]; it could be [w], or [y] or some other variable. The first and last case are straightforward, but the middle case causes difficulty: even though [x] is not free in [n_abs x t], it _is_ free in [t]. Therefore, our induction hypothesis doesn't apply.  To solve this problem, we need to generate a completely fresh variable [z] for the binder, use the lemma above to replace [y] and [w] with it, and then use the induction hypothesis.  *)
Lemma swap_spec_aux : forall m t w y,
size t <= m ->
y `notin` fv_exp (nom_to_exp t) ->
w <> y ->
[w ~> var_f y] (nom_to_exp t) =
nom_to_exp (swap w y t).
Lemma swap_spec : forall t w y,
y `notin` fv_exp (nom_to_exp t) ->
w <> y ->
[w ~> var_f y] (nom_to_exp t) =
nom_to_exp (swap w y t).