(*************************************************************************)
(** * Values and Evaluation *)
(*************************************************************************)
(** In order to state the preservation lemma, we first need to define values and the small-step evaluation relation.  These inductive relations are straightforward to define.  Note the hypotheses which ensure that the relations hold only for locally closed terms.  Below, we prove that this is actually the case, since it is not completely obvious from the definitions alone. *)
Inductive value_c : exp -> Prop :=
| value_abs_c : forall e T1,
lc_c (abs T1 e) ->
value_c (abs T1 e).
Inductive eval_c : exp -> exp -> Prop :=
| eval_beta_c : forall e1 e2 T1,
lc_c (abs T1 e1) ->
value_c e2 ->
eval_c (app (abs T1 e1) e2) (open e1 e2)
| eval_app_1_c : forall e1 e1' e2,
lc_c e2 ->
eval_c e1 e1' ->
eval_c (app e1 e2) (app e1' e2)
| eval_app_2_c : forall e1 e2 e2',
value_c e1 ->
eval_c e2 e2' ->
eval_c (app e1 e2) (app e1 e2').
(** We add the constructors for these two relations as hints to be used by Coq's [auto] and [eauto] tactics. *)
Hint Constructors value_c eval_c.
(*************************************************************************)
(** * Preservation *)
(*************************************************************************)
(** *** Take-home Exercise  Complete the proof of preservation.  In this proof, we proceed by induction on the given typing derivation.  The induction hypothesis has already been appropriately generalized by the given proof fragment.  Proof sketch: By induction on the typing derivation for [e].  - [typing_var_c] case: Variables don't step.  - [typing_abs_c] case: Abstractions don't step.  - [typing_app_c] case: By case analysis on how [e] steps. The [eval_beta] case is interesting, since it follows by the substitution lemma.  The others follow directly from the induction hypotheses. *)
(* HINTS:  - Use [auto] and [eauto], especially with [;], to solve "uninteresting" subgoals.  - Use [inversion] to perform case analyses and to rule out impossible cases.  - In the [eval_beta] subcase of the [typing_app_c] case:  -- Use [inversion] on a typing judgement to obtain a hypothesis about when the body of the abstraction is well-typed.  -- Use [subst_intro] to rewrite the [open] operation into an [open] followed by a [subst].  You'll need to pick a fresh variable first.  *)

Lemma preservation_c : forall (E : env) e e' T,
typing_c E e T ->
eval_c e e' ->
typing_c E e' T.