(***********************************************************************)
(** ** Translating nominal terms to LN terms *)
(***********************************************************************)

(** We decode named terms to LN terms through the use of the
    [close_exp_wrt_exp] function. This function replaces all occurrences of
    a given atom by a new bound variable.

    This function is defined in the [Stlc.Lemmas] module and can be
    automatically generated by LNgen.  *)

Fixpoint nom_to_exp (ne : n_exp) : exp :=
  match ne with
  | n_var x => var_f x
  | n_app e1 e2 => app (nom_to_exp e1) (nom_to_exp e2)
  | n_abs x e1 => abs (close_exp_wrt_exp x (nom_to_exp e1))
end.(* Note that the stack could have some heap definitions in it,
   so we apply the substitutions in the heap there too. *)

Fixpoint apply_stack h (s : list frame) (e :exp) : exp :=
  match s with
  | nil => e
  | n_app2 e' :: s' => apply_stack h s' (app e (apply_heap h (nom_to_exp e')))
  end.(** The full decode function puts all of these parts together. *)

Definition decode (c:configuration) : exp  :=
  match c with
  | (h,e,s) => apply_stack h s (apply_heap h (nom_to_exp e))
  end.Example decode1 : decode conf1 = (app (abs (var_b 0)) (var_f Z)).

(* Specifications: *)
Lemma nom_to_exp_lc : forall t, lc_exp (nom_to_exp t).
Lemma apply_heap_lc : forall h e, lc_exp e -> lc_exp (apply_heap h e).
Lemma apply_stack_lc : forall s h e, lc_exp e -> lc_exp (apply_stack h s e).
Lemma decode_lc : forall c, lc_exp (decode c).
Lemma apply_heap_abs : forall h e, apply_heap h (abs e) = abs (apply_heap h e).
Lemma apply_heap_app : forall h e1 e2, apply_heap h (app e1 e2) = app (apply_heap h e1) (apply_heap h e2).
Lemma apply_heap_open : forall h e e0, lc_exp e0 -> apply_heap h (open e e0) = open (apply_heap h e) (apply_heap h e0).
Lemma apply_stack_cong : forall s h e e', step e e' -> step (apply_stack h s e) (apply_stack h s e').
Lemma aeq_nom_to_exp : forall n1 n2, aeq n1 n2 -> nom_to_exp n1 = nom_to_exp n2.
Lemma nom_to_exp_eq_aeq : forall n1 n2, nom_to_exp n1 = nom_to_exp n2 -> aeq n1 n2.
Lemma apply_heap_get : forall h D x e, scoped_heap D h -> get x h = Some e -> apply_heap h (var_f x) = apply_heap h (nom_to_exp e).
Lemma simulate_step : forall D h e s h' e' s' , machine_step D (h,e,s) = TakeStep _ (h',e',s') -> scoped_conf D (h,e,s) -> decode (h,e,s) = decode (h',e',s') \/ step (decode (h,e,s)) (decode (h',e',s')).
Lemma apply_heap_get_none : forall x h, get x h = None -> apply_heap h (var_f x) = var_f x.
Lemma no_step_stack : forall s h e0, not (is_value e0) -> not (exists e0', step e0 e0') -> not (exists e1, step (apply_stack h s e0) e1).