Require Import Prelims Closures Codes.

Heaps

Class heap PA :=
  {
    Heap : Type;
    HA : Set;
    HC := (PA * HA) % type;
    HE := option (HC * HA);
    get : Heap HA option HE;
    put : Heap HC HA Heap*HA;
    extended H H' := a, get H a None get H a = get H' a;
    HR1: H g a H' b, put H g a = (H', b) get H' b = Some (Some (g,a));
    HR2: H g a H' b, put H g a = (H', b) extended H H';
  }.

Coercion get : Heap > Funclass.

Section heap.
  Variable codeImpl : code.
  Variable C : Code.
  Variable heapImpl : heap PA.
  Implicit Type H : Heap.

  Reserved Notation "a ≫E_ H E" (at level 70, H at level 0, format "a '≫E_' H E").

  Inductive representsEnv H : HA list Clo Prop :=
  | representsEnvNil a:
      H a = Some None
      a E_H []
  | representsEnvCons a b c p P F E:
      H a = Some(Some ((p,b),c))
      p p_C P
      b E_H F
      c E_H E
      a E_H (P/F)::E
  where "a ≫E_ H E" := (representsEnv H a E).

  Hint Constructors representsEnv.

  Lemma representsEnv_functional H:
  functional (representsEnv H).
  Proof.
    intros a E E' . induction in E'|-*; inversion 1;try congruence;repeat f_equal. all:rewrite in ;inv . all:now try eapply representsPro_functional;eauto.
  Qed.


  Lemma representsEnv_extend H H' a E :
    extended H H' a E_H E a E_H' E.
  Proof.
    intros ext. induction 1 as [? eq|? ? ? ? ? ? ? eq].
    -econstructor. erewrite ext in eq. eauto. congruence.
    -econstructor. 2-4:now eauto.
     erewrite ext in eq. eauto. congruence.
  Qed.


  Reserved Notation "g ≫C_ H e" (at level 70,H at level 0, format "g '≫C_' H e").

  Inductive representsClos H : HC Clo Prop :=
    representsClos_C p a P E : p p_C P a E_H E (p,a) C_H P/E
  where "g ≫C_ H e" := (representsClos H g e).
  Hint Constructors representsClos.

  Notation "(≫C( H ) )" := (representsClos H) (at level 0, format "'(≫C(' H ')' ')'").
  (* workaround to prefere "x ≻ y" over "(≻) x y"*) Notation "g ≫C_ H e" := 0.
  Notation "g ≫C_ H e" := (representsClos H g e).

  Lemma representsClos_extend H H' g e :
    extended H H' g C_H e g C_H' e.
  Proof.
    intros ext. inversion 1. all:eauto using representsEnv_extend.
  Qed.



  Fixpoint lookup H a n : option HC:=
    match H a with
      Some (Some (g,a'))
      match n with
        0 Some g
      | S n lookup H a' n
      end
    | _ None
    end.
  Notation "H .[ a , n ]" := (lookup H a n) (at level 1, format "H '.[' a ',' n ]").

  Lemma nth_error_unlinedEnv H a E n e :
    a E_H E E.[n] = Some e g, H.[a,n] = Some g g C_H e.
  Proof.
    induction n in e,a,E|-*;cbn;intros uE eq.
    -inv uE. congruence. inv eq. rewrite . eauto.
    -inv uE. congruence. rewrite . eapply IHn. all:eauto.
  Qed.


  Lemma lookup_unlinedEnv H a E n g :
    a E_H E H.[a,n] = Some g e, E.[n] = Some e g C_H e.
  Proof.
    induction n in g,a,E|-*;cbn;intros uE eq.
    -inv uE;rewrite in *. all:inv eq. eauto.
    -inv uE;rewrite in *. congruence. now eauto.
  Qed.


End heap.

  Notation "H .[ a , n ]" := (lookup H a n) (at level 1, format "H '.[' a ',' n ]").

Hint Constructors representsClos representsEnv.

Instance heapImpl PA: heap PA :=
  {|
    Heap:=list ((PA*nat)*nat);
    HA := nat;
    put H g a:=(H++[(g,a)],S (length H));
    get H a := match a with
                   | 0 => Some None
                   | S a =>
                     match H.[a] with
                     | Some (g,b) => Some (Some (g,b))
                     | None => None
                     end
                   end
  |}.
Proof.
  -intros ? ? ? ? ? [= ]. rewrite nth_error_app2. now rewrite minus_n_n. reflexivity.
  -intros ? ? ? ? ? [= ] [|] neq. easy. destruct nth_error as [[? ?]|] eqn:eq. 2:easy.
   rewrite nth_error_app1;eauto using nth_error_Some_lt. now rewrite eq.
Defined.