(* This program is free software; you can redistribute it and/or      *)
(* modify it under the terms of the GNU Lesser General Public License *)
(* as published by the Free Software Foundation; either version 2.1   *)
(* of the License, or (at your option) any later version.             *)
(*                                                                    *)
(* This program is distributed in the hope that it will be useful,    *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of     *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *)
(* GNU General Public License for more details.                       *)
(*                                                                    *)
(* You should have received a copy of the GNU Lesser General Public   *)
(* License along with this program; if not, write to the Free         *)
(* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *)
(* 02110-1301 USA                                                     *)
(* Contribution to the Coq Library   V6.3 (July 1999)                    *)
(****************************************************************************)
(*                 The Calculus of Inductive Constructions                  *)
(*                                                                          *)
(*                                Projet Coq                                *)
(*                                                                          *)
(*                     INRIA                        ENS-CNRS                *)
(*              Rocquencourt                        Lyon                    *)
(*                                                                          *)
(*                                Coq V5.10                                 *)
(*                              Nov 25th 1994                               *)
(*                                                                          *)
(****************************************************************************)
(****************************************************************************)
(*                              Substitution.v                              *)
(*                                                                          *)
(*                                Gerard Huet                               *)
(*                                                                          *)
(****************************************************************************)
(* Developed in V5.8  January 1993                                          *)
(* Ported    to V5.10 January 1995                                          *)
(****************************************************************************)
(****************************)
(*  Substitution of redexes *)
(****************************)
(* Similar to lift_rec of Terms *)
Fixpoint lift_rec_r (L : redexes) : nat -> nat -> redexes :=
fun k n : nat =>
match L with
| Var i => Var (relocate i k n)
| Fun M => Fun (lift_rec_r M (S k) n)
| Ap b M N => Ap b (lift_rec_r M k n) (lift_rec_r N k n)
end.
Definition lift_r (n : nat) (N : redexes) := lift_rec_r N 0 n.
Definition insert_Var (N : redexes) (i k : nat) :=
match compare k i with
(* k<i *) | inleft (left _) => Var (pred i) (* k=i *) | inleft _ => lift_r k N (* k>i *) | _ => Var i end.  (* Similar to subst_rec of Terms *)
Fixpoint subst_rec_r (L : redexes) : redexes -> nat -> redexes :=
fun (N : redexes) (k : nat) =>
match L with
| Var i => insert_Var N i k
| Fun M => Fun (subst_rec_r M N (S k))
| Ap b M M' => Ap b (subst_rec_r M N k) (subst_rec_r M' N k)
end.
Definition subst_r (N M : redexes) := subst_rec_r M N 0.
(* Lifting lemmas *)

(* Specifications: *)
Lemma lift_le :
forall n i k : nat, k <= i -> lift_rec_r (Var i) k n = Var (n + i).
Lemma lift_gt : forall n i k : nat, k > i -> lift_rec_r (Var i) k n = Var i.
Lemma lift1 :
forall (U : redexes) (j i k : nat),
lift_rec_r (lift_rec_r U i j) (j + i) k = lift_rec_r U i (j + k).
Lemma lift_lift_rec :
forall (U : redexes) (k p n i : nat),
i <= n ->
lift_rec_r (lift_rec_r U i p) (p + n) k = lift_rec_r (lift_rec_r U n k) i p.
Lemma lift_lift :
forall (U : redexes) (k p n : nat),
lift_rec_r (lift_r p U) (p + n) k = lift_r p (lift_rec_r U n k).
Lemma liftrecO : forall (U : redexes) (n : nat), lift_rec_r U n 0 = U.
Lemma liftO : forall U : redexes, lift_r 0 U = U.
Lemma lift_rec_lift_rec :
forall (U : redexes) (n p k i : nat),
k <= i + n ->
i <= k -> lift_rec_r (lift_rec_r U i n) k p = lift_rec_r U i (p + n).
Lemma lift_rec_lift :
forall (U : redexes) (n p k i : nat),
k <= n -> lift_rec_r (lift_r n U) k p = lift_r (p + n) U.