Plain.Context

Context

Require Import Omega List Program.Equality.
Require Import Autosubst.Autosubst.

Fixpoint atn {X} l n (x : X) :=
  match l with
    | nil False
    | y :: l' match n with
                  | 0 x = y
                  | S n' atn l' n' x
                end
  end.

Section SubstInstance.

Context {term : Type}.
Context {Ids_term : Ids term} {Rename_term : Rename term}
  {Subst_term : Subst term} {SubstLemmas_term : SubstLemmas term}.

Inductive atnd: list term var term Prop :=
| Atnd0 A A' :
    A' = A.[ren(+1)] atnd (A :: ) 0 A'
| AtndS x A B B' :
    atnd x B B' = B.[ren(+1)] atnd (A :: ) (S x) B'.

Lemma atn_mmap {f : term term} { x A A'} :
  atn x A A' = (f A) atn (mmap f ) x A'.
Proof.
  revert x.
  induction ; intros; simpl in *; trivial.
  destruct x; subst; eauto.
Qed.


Lemma mmap_atn {f : term term} { x A'} :
  atn (mmap f ) x A' A, A' = (f A) atn x A.
Proof.
  revert x. induction ; intros; simpl in *.
  - contradiction.
  - destruct x; subst; eauto.
Qed.


Lemma up_mmap_atn A x :
  ( x B, atn x B atn ( x) B.[ren ])
  atn (mmap (subst (ren (+1))) ) x A
  atn (mmap (subst (ren (+1))) ) ( x) A.[ren (0 .: >>> (+1))].
Proof.
  intros .
  edestruct (mmap_atn ) as [? [? ?]]. subst.
  eapply atn_mmap; eauto. autosubst.
Qed.


Lemma up_atnd A B x:
  ( x C, atnd x C atnd ( x) C.[ren ])
  atnd (A :: ) x B
  atnd (A.[ren ] :: ) ((0 .: >>> (+1)) x) B.[ren (0 .: >>> (+1))].
Proof.
  intros ; destruct x; simpl; inv ; econstructor; eauto; autosubst.
Qed.


Lemma atnd_steps x A :
  atnd x A
  atnd ( ) (length + x) A.[ren(+(length ))].
Proof.
  revert A x.
  induction ; intros.
  - split.
    + autosubst.
    + autosubst.
  - simpl. cutrewrite (A.[ren (+S (length ))] =
                       A.[ren(+length )].[ren(+1)]); [idtac|autosubst].
    split.
      + econstructor. eapply IHDelta; eassumption. reflexivity.
      + intros H. inv H. rewrite IHDelta. apply lift_inj in .
        subst. eassumption.
Qed.


Lemma atnd_steps' x A :
  atnd ( ) (x + length ) A
   B, A = B.[ren(+(length ))] atnd x B.
Proof.
  revert A x.
  induction ; intros.
  - exists A.
    simpl in H.
    rewrite plus_0_r in H. intuition autosubst.
  - asimpl. simpl in *.
    rewrite plusnS in *.
    inv H.
    edestruct IHDelta as [B' [? ?]]; eauto. exists B'. subst.
    intuition autosubst.
Qed.


Corollary atnd_step A x B :
  atnd x A atnd (B :: ) (S x) A.[ren(+1)].
Proof.
  apply atnd_steps with ( := B :: nil).
Qed.


Lemma atnd_repl A :
  (atnd ( A :: ) (length ) A.[ren(+ S (length ))])
  ( x B A',
     x length atnd ( A :: ) x B
     atnd ( A' :: ) x B).
Proof.
  split.
  - pose proof (atnd_steps 0 (A :: ) A.[ren(+1)]) as H. asimpl in H.
    apply H. now constructor.
  - intros x. revert A .
    induction x; intros A H B A' H_atn.
    + destruct as [| C ]. { now intuition. }
      simpl in *.
      inv H_atn. now constructor.
    + destruct as [| C ]; simpl in *.
      * inv H_atn. econstructor. eassumption. reflexivity.
      * inv H_atn. econstructor. eapply IHx; eauto. reflexivity.
Qed.


Lemma atnd_defined x : ( B, atnd x B) x < length .
Proof.
  revert x. induction ; intuition; asimpl in *; ainv.
  - destruct x. omega. cut(x < length ). omega.
    ainv. firstorder.
  - destruct x.
    + eexists. now econstructor.
    + edestruct IHDelta as [_ [? ?]]. cut(x < length ); eauto. omega.
      eexists. econstructor; eauto.
Qed.


End SubstInstance.

(* Local Variables: *)
(* coq-load-path: (("." "Plain") ("../../theories" "Autosubst")) *)
(* End: *)