Require Import Interpreter Encodings.

Definition test (u : term) := forall n, u (enc n) T \/ u (enc n) F.
Definition satis u n := u (enc n) T.

Hint Unfold test.

Section fix_u.

Variable u : term.
Hypothesis proc_u : proc u.
Hypothesis test_u : test u.

Definition H := rho (.\"H", "n", "u"; "u" "n" (.\ "_"; "n") (.\ "_"; "H" (!Succ "n") "u") !I).
Hint Unfold H : cbv.

Lemma H_rec n : H (enc n) u ≻^+ u (enc n) (lambda (enc n)) (lambda (H (Succ (enc n)) u)) I.
Proof.
eexists. split; solvered.
Qed.

Definition ok n := exists k, H (enc n) u enc k /\ satis u k.

Lemma H_ok n : satis u n -> ok n.
Proof.
intros. exists n. rewrite H_rec, H0; eauto. split. solveeq. eauto.
Qed.

Lemma H_n_Sn n : ok (S n) -> ok n.
Proof with eauto.
intros H_Sk. destruct (test_u n).
- intros. exists n.
rewrite H_rec, H0; eauto. split. solveeq. eauto.
- destruct (H_Sk) as (k & ?). exists k.
rewrite H_rec, H0; eauto. split. eapply evaluates_equiv. split; value.
transitivity (H (Succ (enc n)) u). solveeq.
rewrite Succ_correct. now eapply evaluates_equiv. firstorder.
Qed.

Lemma H_0_n n : test u -> ok n -> ok 0.
Proof.
induction n; eauto using H_n_Sn.
Qed.

Definition C := lambda (H (enc 0) 0).

Lemma C_complete n : satis u n -> exists n, C u enc n /\ satis u n.
Proof.
intros sat % H_ok. destruct (H_0_n test_u sat) as [k [H_sat % evaluates_equiv ?]]; eauto. exists k.
split; eauto.
eapply evaluates_equiv; split; value. transitivity (H (enc 0) u).
solveeq. firstorder.
Qed.

Lemma H_correct n k v : H (enc n) u ▷^k v -> exists n, satis u n.
Proof.
revert n v.
eapply complete_induction with (x := k). clear k.
intros k IHn n v He.

destruct (test_u n).
- firstorder.
- assert (H (enc n) u ≻^+ H (enc (S n)) u).
eapply (stepplus_star_stepplus (H_rec _)).
eapply evaluates_star in H0 as []. rewrite H0.
transitivity (H (Succ (enc n)) u). solvered. now rewrite Succ_correct.
now destruct (triangle He H1) as (? & ? & ? % IHn).
Qed.

Lemma C_sound : eva (C u) -> exists n, satis u n.
Proof with eauto.
assert (He : C u H (enc 0) u). solveeq. rewrite He.
intros [v [[k Hv] % star_stepn lam_v] % evaluates_star].
eapply H_correct. split...
Qed.

End fix_u.