(*************************************************************************)
(** * 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).(*************************************************************************)
(** * 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').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').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').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').

Lemma progress_c : forall e T, typing_c nil e T -> value_c e \/ exists e', eval_c e e'.