From Undecidability.L Require Export Prelim.ARS Prelim.MoreBase.
From Undecidability.Shared.Libs.PSL Require Export Base Bijection.
From Undecidability.L Require Export L.
Hint Constructors ARS.star : cbv.
(* * The call-by-value lambda calculus L *)
(* ** Syntax   *)
Notation "'#' v" := (var v) (at level 1).
(* Notation "(λ  s )" := (lam s) (right associativity, at level 0).  *)
Instance term_eq_dec : eq_dec term.
Hint Resolve lambda_lam : core.
Instance lambda_dec s : dec (lambda s).
Instance bound_dec k s : dec (bound k s).
Proof with try ((left; econstructor; try lia; tauto) || (right; inversion 1; try lia; tauto)).
revert k; induction s; intros k.
- destruct (le_lt_dec n k) as [Hl | Hl]... destruct (le_lt_eq_dec _ _ Hl)...
- destruct (IHs1 k), (IHs2 k)...
- induction k.
+ destruct (IHs 1)...
+ destruct (IHs (S (S k)))...
Defined.
Instance closed_dec s : dec (closed s).
Proof with try tauto.
intros cls_s. induction s.
- eapply closed_dcl in cls_s. inv cls_s. lia.
- eapply closed_app in cls_s. destruct IHs1 as [[C [t A]] | A], IHs2 as [[D [t' B]] | B]...
+ right. subst. eexists. eauto.
+ right; subst. firstorder; eexists. eapply stepAppR. eassumption.
+ right; subst. firstorder; eexists. eapply stepAppL. eassumption.
+ right. subst. firstorder. eexists. eapply stepAppR. eassumption.
- left. split. eassumption. firstorder.
Qed.
Goal forall s, closed s -> ((~ exists t, s ≻ t) <-> proc s).
(* Properties of the reduction relation *)
Proof with repeat inv_step; eauto using step.
intros s; induction s; intros t1 t2 step_s_t1 step_s_t2; try now inv step_s_t2.
inv step_s_t1.
- inv step_s_t2; try eauto; inv_step.
- inv step_s_t2...
+ destruct (IHs2 _ _ H2 H3).
* left. congruence.
* right. destruct H as [u [A B]]...
+ right...
- inv step_s_t2...
+ right...
+ destruct (IHs1 _ _ H2 H3).
* left. congruence.
* right. destruct H as [u [A B]]...
Qed.
Notation "s '>(' l ')' t" := (pow step l s t) (at level 50, format "s  '>(' l ')'  t").
Arguments pow: simpl never.
(* Properties of the reflexive, transitive closure of reduction *)
Notation "s '>*' t" := (star step s t) (at level 50).
Instance star_PreOrder : PreOrder (star step).
Instance step_star_subrelation : subrelation step (star step).
Instance star_step_app_proper :
Proper ((star step) ==> (star step) ==> (star step)) app.
Instance star_closed_proper :
Proper ((star step) ==> Basics.impl) closed.
Proof with eauto using ecl, equiv.
split; induction 1...
- eapply ecl_sym...
- eapply ecl_trans...
Qed.
Hint Resolve star_equiv : core.
Instance star_equiv_subrelation : subrelation (star step) equiv.
Instance step_equiv_subrelation : subrelation step equiv.
Proof with eauto using equiv, step.
intros H; revert u u'; induction H; intros z z' H'...
- eapply eqTrans. eapply eqStep. eapply stepAppL. eassumption.
induction H'...
- induction H'...
Qed.
Instance equiv_app_proper :
Proper (equiv ==> equiv ==> equiv) app.
(* Definition of convergence *)
Definition converges s := exists t, s == t /\ lambda t.
Instance converges_proper :
Proper (equiv ==> iff) converges.
(* Lemma eq_lam s t : lambda s -> lambda t -> lam s == lam t <-> s = t.  Lemma unique_normal_forms' (s t t' : term) : s == lam t -> s == lam t' -> lam t = lam t'.  Lemma unique_normal_forms (s t : term) : lambda s -> lambda t ->  s == t -> s = t.  (* Eta expansion *)
(* Useful lemmas *)
Instance pow_star_subrelation i: subrelation (pow step i) (star step).
(* Definition of evaluation *)
Definition eval s t := s >* t /\ lambda t.
Notation "s '⇓' t" := (eval s t) (at level 51).
Hint Unfold eval : core.
Instance eval_star_subrelation : subrelation eval (star step).
Instance reduce_eval_proper : Proper (Basics.flip (star step) ==> eq ==> Basics.impl) eval.
Definition evalIn i s t := s >(i) t /\ lambda t.
Notation "s '⇓(' l ')' t" := (evalIn l s t) (at level 50, format "s  '⇓(' l ')'  t").
Definition redLe l s t := exists i , i <= l /\ pow step i s t.
Notation "s '>(<=' l ')' t" := (redLe l s t) (at level 50, format "s  '>(<=' l ')'  t").
Definition evalLe l s t := s >(<=l) t /\ lambda t.
Notation "s '⇓(<=' l ')' t" := (evalLe l s t) (at level 50, format "s  '⇓(<=' l ')'  t").
Instance evalLe_eval_subrelation i: subrelation (evalLe i) eval.

Lemma evalLe_evalIn s t k:
s ⇓(<=k) t -> exists k', k' <= k /\ s ⇓(k') t.