Require Import Undecidability.Shared.Libs.PSL.Base.
Require Import FunInd.
From Undecidability.L Require Export Prelim.ARS Prelim.MoreBase AbstractMachines.FlatPro.Programs.
Definition HAdd : Type := nat.
Definition HClos : Type := HAdd * Pro.
Definition HEntr : Type := option (HClos * HAdd).
Definition Heap : Type := list HEntr.
Section Semantics.
Implicit Types H : Heap.
Implicit Types T V : list HClos.
Implicit Types n m : nat.
Implicit Types a b c : HAdd.
Implicit Types g : HClos.
Implicit Types P Q : Pro.
Definition put H e : HAdd * Heap := (|H|, H++[e]).
Definition tailRecursion : HClos -> list HClos -> list HClos :=
fun '(a, P) T =>
match P with
| [] => T
| _ => (a, P) :: T
end.
Definition state : Type := list HClos * list HClos * Heap.
Fixpoint jumpTarget (k:nat) (Q:Pro) (P:Pro) : option (Pro*Pro) :=
match P with
| retT :: P' => match k with
| 0 => Some (Q,P')
| S k' => jumpTarget k' (Q++[retT]) P'
end
| lamT :: P' => jumpTarget (S k) (Q++[lamT]) P'
| t :: P' => jumpTarget k (Q++[t]) P'
| [] => None
end.
Fixpoint lookup H a n : option HClos :=
match nth_error H a with
| Some (Some (g, b)) =>
match n with
| 0 => Some g
| S n' => lookup H b n'
end
| _ => None
end.
Lemma lookup_eq H a n :
lookup H a n =
match nth_error H a with
| Some (Some (g, b)) =>
match n with
| 0 => Some g
| S n' => lookup H b n'
end
| _ => None
end.
Proof. destruct n; auto. Qed.
Inductive step : state -> state -> Prop :=
| step_pushVal P P' Q a T V H :
jumpTarget O [] P = Some (Q, P') ->
step ((a, (lamT :: P)) :: T, V, H) (tailRecursion (a, P') T, (a, Q) :: V, H)
| step_beta a b g P Q H H' c T V :
put H (Some (g, b)) = (c, H') ->
step ((a, (appT :: P)) :: T, g :: (b, Q) :: V, H) ((c, Q) :: tailRecursion (a, P) T, V, H')
| step_load P a n g T V H :
lookup H a n = Some g ->
step ((a, (varT n :: P)) :: T, V, H) (tailRecursion (a, P) T, g :: V, H)
.
Definition halt_state (s : state) : Prop :=
forall s', ~ step s s'.
Definition steps : state -> state -> Prop := star step.
Definition steps_k : nat -> state -> state -> Prop := pow step.
Corollary steps_k_steps (s s' : state) (k : nat) :
steps_k k s s' -> steps s s'.
Proof. intros. apply star_pow. eauto. Qed.
Corollary steps_steps_k (s s' : state) :
steps s s' -> exists k, steps_k k s s'.
Proof. intros. apply star_pow. eauto. Qed.
Definition halts (s : state) : Prop :=
exists s', steps s s' /\ halt_state s'.
Definition halts_k (s : state) (k : nat) : Prop :=
exists s', steps_k k s s' /\ halt_state s'.
Definition step_fun : state -> option state :=
fun '(T, V, H) =>
match T with
| (a, (lamT :: P)) :: T =>
match jumpTarget O [] P with
| Some (Q, P') =>
Some (tailRecursion (a, P') T, (a, Q) :: V, H)
| _ => None
end
| (a, (appT :: P)) :: T =>
match V with
| g :: (b, Q) :: V =>
let (c, H') := put H (Some (g, b)) in
Some ((c, Q) :: tailRecursion (a, P) T, V, H')
| _ => None
end
| (a, (varT x :: P)) :: T =>
match lookup H a x with
| Some g => Some (tailRecursion (a, P) T, g :: V, H)
| _ => None
end
| _ => None
end.
Functional Scheme step_fun_ind := Induction for step_fun Sort Prop.
Lemma step_step_fun : forall s s', step s s' -> step_fun s = Some s'.
Proof.
intros s s' HStep. induction HStep; cbn in *; auto.
- now rewrite H0.
- now inv H0.
- now rewrite H0.
Qed.
Lemma step_fun_step : forall s s', step_fun s = Some s' -> step s s'.
Proof.
intros s. functional induction (step_fun s); intros s' HEq; cbn; try congruence.
- inv HEq. now econstructor.
- inv HEq. now econstructor.
- inv HEq. now econstructor.
Qed.
Lemma step_iff : forall s s', step s s' <-> step_fun s = Some s'.
Proof. split; auto using step_step_fun, step_fun_step. Qed.
Lemma step_functional : functional step.
Proof. hnf. intros x z1 z2 H1 % step_iff H2 % step_iff. congruence. Qed.
Definition is_halt_state (s : state) : bool :=
match step_fun s with
| Some s' => false
| None => true
end.
Lemma is_halt_state_halt (s : state) :
is_halt_state s = true -> halt_state s.
Proof.
unfold is_halt_state, halt_state in *.
intros H.
destruct (step_fun s) eqn:EStep; inv H.
intros s' H % step_iff. congruence.
Qed.
Lemma halt_state_is_halt_state (s : state) :
halt_state s -> is_halt_state s = true.
Proof.
unfold is_halt_state, halt_state in *.
intros H.
destruct (step_fun s) eqn:EStep; auto.
apply step_iff in EStep. specialize (H s0). tauto.
Qed.
Lemma is_halt_state_correct (s : state) :
is_halt_state s = true <-> halt_state s.
Proof. intros. split; auto using is_halt_state_halt, halt_state_is_halt_state. Qed.
Lemma step_is_halt_state (s s' : state) :
step s s' -> is_halt_state s = false.
Proof.
intros H. destruct (is_halt_state) eqn:EHaltState; auto. exfalso.
apply is_halt_state_correct in EHaltState. eapply EHaltState; eauto.
Qed.
Global Instance halt_state_dec : forall s, dec (halt_state s).
Proof. intros s. eapply dec_transfer. apply is_halt_state_correct. auto. Defined.
Lemma halt_state_steps s s' :
halt_state s -> steps s s' -> s' = s.
Proof.
intros HHalt HSteps. hnf in HHalt.
destruct HSteps; auto. now specialize (HHalt _ H).
Qed.
Lemma halt_state_steps_k s s' k :
halt_state s -> steps_k k s s' -> s' = s /\ k = 0.
Proof.
intros HHalt HSteps. hnf in HHalt.
destruct k;destruct HSteps; auto. destruct H. now specialize (HHalt _ H).
Qed.
End Semantics.
Definition largestVarC : HClos -> nat := (fun '(_,P) => largestVarP P).
Definition largestVarCs (T:list HClos) :=
maxl (map largestVarC T).
Definition largestVarHE (h:HEntr) :=
match h with
None => 0
| Some (c,_) => largestVarC c
end.
Definition largestVarH (H:list HEntr) :=
maxl (map largestVarHE H).