theory WTLemma
  imports GenSubEnv WellTypedExp PermEnvMisc NormEnv
begin

    (*
      ####################################
        P2. general well-typed lemmas
      ####################################
    *)

lemma well_typed_perm_leq: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx \<rbrakk> \<Longrightarrow> leq_use_env r_s2 r_s1"
  apply (induct e arbitrary: env r_s1 tau r_s2 rx)
        apply (auto)
      apply (rule_tac r_sb="diff_use_env r_s1 (comp_use_env (ereq_use_env x1a tau_x) r_ex)" in trans_leq_use_env)
       apply (rule_tac self_diff_leq_use_env)
      apply (simp)
     apply (rule_tac r_sb="diff_use_env r_s3 r_ex" in trans_leq_use_env)
      apply (rule_tac diff_leq_use_env)
      apply (rule_tac r_sb="r_s2a" in trans_leq_use_env)
       apply (auto)
    apply (rule_tac r_sb="r_s2a" in trans_leq_use_env)
     apply (auto)
   apply (rule_tac r_sb="diff_use_env r_s1 r_ex" in trans_leq_use_env)
    apply (rule_tac self_diff_leq_use_env)
   apply (simp)
  apply (rule_tac r_sb="r_s2a" in trans_leq_use_env)
   apply (auto)
  apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
   apply (auto)
  apply (rule_tac r_sb="diff_use_env r_s3 (comp_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_ex)" in trans_leq_use_env)
   apply (rule_tac self_diff_leq_use_env)
  apply (simp)
  done

lemma well_typed_perm_leqx: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx \<rbrakk> \<Longrightarrow> leq_use_env rx r_s2"
  apply (induct e arbitrary: env r_s1 tau r_s2 rx)
       apply (auto)
    (* if case *)
  apply (rule_tac dist_comp_leq_use_env)
   apply (auto)
  done

lemma well_typed_spec_perm_leq: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx \<rbrakk> \<Longrightarrow> leq_perm (r_s2 x) (r_s1 x)"
  apply (cut_tac ?r_s2.0="r_s2" and ?r_s1.0="r_s1" in well_typed_perm_leq)
   apply (auto)
  apply (simp add: leq_use_env_def)
  done

    (*
      ####################################
        P3. well-typed free var lemmas
      ####################################
    *)

lemma well_typed_fv_env_use: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; x \<in> free_vars e \<rbrakk> \<Longrightarrow> env x \<noteq> None"
  (*apply (simp add: env_gen_use_def)*)
  apply (induction e arbitrary: env tau r_s1 r_s2 rx)
       apply (auto)
  apply (case_tac "\<exists> y. add_env env x1a t1 x = Some y")
   apply (simp add: add_env_def)
   apply (auto)
  done

lemma well_typed_rv_env_use: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; x \<in> ref_vars e \<rbrakk> \<Longrightarrow> env x \<noteq> None"
  (*apply (simp add: env_gen_use_def)*)
  apply (induction e arbitrary: env tau r_s1 r_s2 rx)
        apply (auto)
   apply (case_tac "x = x1a")
    apply (auto)
   apply (case_tac x2a)
     apply (auto)
   apply (simp add: deref_name_def)
  apply (case_tac "x = x1a")
   apply (auto)
  apply (case_tac "\<exists> y. add_env env x1a t1 x = Some y")
   apply (simp add: add_env_def)
   apply (auto)
  done

lemma well_typed_no_npv_use: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; r_s1 x = NoPerm \<rbrakk> \<Longrightarrow> x \<notin> non_prim_vars env e"
  apply (induction e arbitrary: env r_s1 tau r_s2 rx)
       apply (auto)
    (* const + op case *)
        apply (simp add: non_prim_vars_def)
       apply (simp add: non_prim_vars_def)
    (* var case. *)
      apply (cut_tac r_x="ereq_use_env x1a tau_x" and r_s="r_s1" in leq_use_none)
        apply (auto)
      apply (case_tac "x \<noteq> x1a")
       apply (simp add: non_prim_vars_def)
      apply (cut_tac x="x" and tau="tau_x" in ereq_use_none)
       apply (auto)
      apply (simp add: non_prim_vars_def)
      apply (simp add: non_prim_entry_def)
    (* pair case 1 *)
     apply (case_tac "x \<notin> free_vars (PairExp e1 e2)")
      apply (simp add: non_prim_vars_def)
     apply (auto)
      apply (simp add: non_prim_vars_def)
    (* pair case 2 *)
     apply (cut_tac r_x="r_s2a" and r_s="r_s1" and x="x" in leq_use_none)
       apply (rule_tac well_typed_perm_leq)
       apply (auto)
     apply (simp add: non_prim_vars_def)
    (* if case 1 *)
    apply (case_tac "x \<notin> free_vars (IfExp e1 e2 e3)")
     apply (simp add: non_prim_vars_def)
    apply (auto)
      apply (case_tac "x \<notin> non_prim_vars env e1")
      apply (simp add: non_prim_vars_def)
      apply (auto)
    (* if case 2 *)
     apply (cut_tac r_x="r_s2a" and r_s="r_s1" and x="x" in leq_use_none)
       apply (rule_tac well_typed_perm_leq)
       apply (auto)
     apply (case_tac "x \<notin> non_prim_vars env e2")
      apply (simp add: non_prim_vars_def)
     apply (auto)
    (* if case 3 *)
     apply (cut_tac r_x="r_s2a" and r_s="r_s1" and x="x" in leq_use_none)
       apply (rule_tac well_typed_perm_leq)
       apply (auto)
    apply (case_tac "x \<notin> non_prim_vars env e3")
     apply (simp add: non_prim_vars_def)
    apply (auto)
    (* lambda case *)
    apply (case_tac "x \<noteq> x1a")
     apply (auto)
    apply (cut_tac r_x="rxa" and r_s="r_s1" and x="x" in leq_use_none)
      apply (auto)
    apply (cut_tac r_s="rxa" and y="x1a" and r="r" and x="x" in add_use_none_rev)
      apply (auto)
    apply (case_tac "x \<notin> non_prim_vars (add_env env x1a t1) e")
     apply (simp add: non_prim_vars_def)
    apply (case_tac "\<not> non_prim_entry (add_env env x1a t1) x")
      apply (simp add: non_prim_entry_def)
      apply (simp add: add_env_def)
      apply (auto)
   apply (simp add: non_prim_vars_def)
    (* app case 1 *)
  apply (case_tac "x \<notin> free_vars (AppExp e1 e2)")
   apply (simp add: non_prim_vars_def)
  apply (auto)
   apply (case_tac "x \<notin> non_prim_vars env e1")
    apply (simp add: non_prim_vars_def)
   apply (auto)
    (* app case 2 *)
  apply (cut_tac r_x="r_s2a" and r_s="r_s1" and x="x" in leq_use_none)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
  apply (case_tac "x \<notin> non_prim_vars env e2")
   apply (simp add: non_prim_vars_def)
  apply (auto)
  done

(*
lemma well_typed_no_fv_use: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; r_s1 x = NoPerm \<rbrakk> \<Longrightarrow> x \<notin> free_vars e"
  apply (induction e arbitrary: env r_s1 tau r_s2 rx)
       apply (auto)
    (* var case *)
        apply (cut_tac r_x="req_use_env x tau" and r_s="r_s1" in leq_use_none)
          apply (auto)
        apply (cut_tac x="x" in req_use_none)
        apply (auto)
    (* if case 1 *)
       apply (metis)
    (* if case 2 *)
      apply (cut_tac r_x="r_s2a" and r_s="r_s1" and x="x" in leq_use_none)
        apply (rule_tac well_typed_perm_leq)
        apply (auto)
      apply (metis)
    (* if case 3 *)
     apply (cut_tac r_x="r_s2a" and r_s="r_s1" and x="x" in leq_use_none)
       apply (rule_tac well_typed_perm_leq)
       apply (auto)
     apply (metis)
    (* lambda case *)
    apply (case_tac "x \<noteq> x1a")
     apply (auto)
    apply (cut_tac r_x="rxa" and r_s="r_s1" and x="x" in leq_use_none)
      apply (auto)
    apply (cut_tac r_s="rxa" and y="x1a" and r="r" and x="x" in  add_use_none_rev)
      apply (auto)
    apply (metis)
    (* app case 1 *)
   apply (metis)
    (* app case 2 *)
  apply (cut_tac r_x="r_s2a" and r_s="r_s1" and x="x" in leq_use_none)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
  apply (metis)
  done    *)

lemma well_typed_aff_fv_own: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; x \<in> free_vars e; env x = Some t; req_type t = Aff \<rbrakk> \<Longrightarrow> r_s1 x = OwnPerm"
  apply (induction e arbitrary: env r_s1 tau r_s2 rx)
       apply (auto)
    (* var case *)
       apply (case_tac "ereq_use_env x t x \<noteq> OwnPerm")
        apply (simp add: ereq_use_env_def)
        apply (simp add: end_req_perm_def)
        apply (simp add: one_use_env_def)
       apply (cut_tac r_x="ereq_use_env x t" and r_s="r_s1" and x="x" in leq_use_own)
         apply (auto)
    (* pair case 2 *)
      apply (rule_tac r_x="r_s2a" in leq_use_own)
       apply (auto)
      apply (rule_tac well_typed_perm_leq)
      apply (auto)
    (* if case 2 *)
     apply (rule_tac r_x="r_s2a" in leq_use_own)
      apply (auto)
     apply (rule_tac e="e1" in well_typed_perm_leq)
     apply (auto)
    (* if case 3 *)
    apply (rule_tac r_x="r_s2a" in leq_use_own)
     apply (auto)
    apply (rule_tac e="e1" in well_typed_perm_leq)
    apply (auto)
    (* lambda case *)
   apply (rule_tac r_x="rxa" in leq_use_own)
    apply (auto)
   apply (case_tac "\<not> add_use_env rxa x1a r x = OwnPerm")
    apply (auto)
    apply (case_tac "\<not> add_env env x1a t1 x = Some t")
     apply (simp add: add_env_def)
    apply (auto)
   apply (simp add: add_use_env_def)
    (* app case *)
  apply (rule_tac r_x = "r_s2a" in leq_use_own)
   apply (auto)
  apply (rule_tac e="e1" in well_typed_perm_leq)
  apply (auto)
  done

  (*
lemma well_typed_fv_start_use: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; x \<in> free_vars e; env x = Some t; aff_fun_ty t \<rbrakk> \<Longrightarrow> r_s1 x = OwnPerm"
  apply (induction e arbitrary: env r_s1 tau r_s2 rx)
       apply (auto)
    (* var case *)
      apply (case_tac "req_use_env x t x \<noteq> OwnPerm")
       apply (simp add: req_use_env_def)
       apply (simp add: start_req_perm_def)
       apply (simp add: one_use_env_def)
      apply (cut_tac r_x="req_use_env x t" and r_s="r_s1" and x="x" in leq_use_own)
        apply (auto)
    (* if case 2 *)
     apply (rule_tac r_x="r_s2a" in leq_use_own)
      apply (auto)
     apply (rule_tac e="e1" in well_typed_perm_leq)
     apply (auto)
    (* if case 3 *)
    apply (rule_tac r_x="r_s2a" in leq_use_own)
     apply (auto)
    apply (rule_tac e="e1" in well_typed_perm_leq)
    apply (auto)
    (* lambda case *)
   apply (rule_tac r_x="rxa" in leq_use_own)
    apply (auto)
   apply (case_tac "\<not> add_use_env rxa x1a r x = OwnPerm")
    apply (auto)
    apply (case_tac "\<not> add_env env x1a t1 x = Some t")
     apply (simp add: add_env_def)
    apply (auto)
   apply (simp add: add_use_env_def)
    (* app case*)
  apply (rule_tac r_x = "r_s2a" in leq_use_own)
   apply (auto)
  apply (rule_tac e="e1" in well_typed_perm_leq)
  apply (auto)
  done*)

    (*
      ####################################
        P4. well-typed manipulation for type environments
      ####################################
    *)

lemma well_typed_add_vars: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; x \<notin> free_vars e; x \<notin> ref_vars e \<rbrakk> \<Longrightarrow> well_typed (add_env env x t) r_s1 e tau r_s2 rx"
  apply (induct e arbitrary: env r_s1 tau r_s2 rx)
        apply (auto)
    (* var case *)
       apply (simp add: add_env_def)
       apply (simp add: deref_name_def)
       apply (case_tac x2a)
        apply (auto)
       apply (simp add: add_env_def)
       apply (auto)
    (* pair case *)
      apply (rule_tac x="r_s2a" in exI)
      apply (rule_tac x="r_s3" in exI)
      apply (rule_tac x="rx1" in exI)
      apply (auto)
      apply (rule_tac x="rx2" in exI)
      apply (auto)
    (* if case *)
     apply (rule_tac x="rx'" in exI)
     apply (rule_tac x="r_s2a" in exI)
     apply (auto)
     apply (rule_tac x="rx1" in exI)
     apply (auto)
     apply (rule_tac x="rx2" in exI)
     apply (auto)
    (* lambda case 1 *)
    apply (rule_tac x="rxa" in exI)
    apply (auto)
    apply (rule_tac x="r_end" in exI)
    apply (rule_tac x="r_s'" in exI)
    apply (case_tac "x = x1a")
     apply (cut_tac env="env" and x="x" and t="t" and t'="t1" in double_add_env)
     apply (auto)
    apply (cut_tac env="env" and x="x1a" and y="x" and t="t" and t'="t1" in almost_comm_add_env)
     apply (auto)
    (* lambda case 2 *)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
   apply (rule_tac x="r_end" in exI)
   apply (rule_tac x="r_s'" in exI)
   apply (cut_tac env="env" and x="x" and t="t" and t'="t1" in double_add_env)
   apply (auto)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="r_s2a" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (rule_tac x="r_s3" in exI)
  apply (auto)
  done

lemma well_typed_rem_vars: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; x \<notin> free_vars e; x \<notin> ref_vars e \<rbrakk> \<Longrightarrow> well_typed (rem_env env x) r_s1 e tau r_s2 rx"
  apply (induct e arbitrary: env r_s1 tau r_s2 rx)
        apply (auto)
    (* var case *)
        apply (simp add: rem_env_def)
        apply (simp add: deref_name_def)
        apply (case_tac x2a)
         apply (auto)
       apply (simp add: rem_env_def)
       apply (auto)
    (* pair case *)
      apply (rule_tac x="r_s2a" in exI)
      apply (rule_tac x="r_s3" in exI)
      apply (rule_tac x="rx1" in exI)
      apply (auto)
      apply (rule_tac x="rx2" in exI)
      apply (auto)
    (* if case *)
     apply (rule_tac x="rx'" in exI)
     apply (rule_tac x="r_s2a" in exI)
     apply (auto)
     apply (rule_tac x="rx1" in exI)
     apply (auto)
     apply (rule_tac x="rx2" in exI)
     apply (auto)
    (* lambda case 1 *)
    apply (rule_tac x="rxa" in exI)
    apply (auto)
    apply (rule_tac x="r_end" in exI)
    apply (rule_tac x="r_s'" in exI)
    apply (case_tac "x = x1a")
     apply (cut_tac env="env" and x="x" and t="t1" in partial_add_rem_env)
    apply (auto)
    apply (cut_tac env="env" and x="x" and y="x1a" and t="t1" in almost_comm_add_rem_env)
     apply (auto)
    (* lambda case 2 *)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
   apply (rule_tac x="r_end" in exI)
   apply (rule_tac x="r_s'" in exI)
   apply (cut_tac env="env" and x="x" and t="t1" in partial_add_rem_env)
   apply (auto)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="r_s2a" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (rule_tac x="r_s3" in exI)
  apply (auto)
  done

lemma well_typed_add_vars_rev: "\<lbrakk> well_typed (add_env env x t) r_s1 e tau r_s2 rx; x \<notin> free_vars e; x \<notin> ref_vars e \<rbrakk> \<Longrightarrow> well_typed env r_s1 e tau r_s2 rx"
  apply (cut_tac env="add_env env x t" and ?r_s1.0="r_s1" and e="e" and tau="tau" and ?r_s2.0="r_s2" and rx="rx" and x="x" in well_typed_rem_vars)
    apply (auto)
  apply (case_tac "env x = None")
   apply (auto)
   apply (cut_tac env="env" and x="x" and t="t" in cancel_rem_add_env)
    apply (auto)
  apply (rule_tac t="well_typed env r_s1 e tau r_s2 rx" and s="well_typed (add_env (rem_env env x) x y) r_s1 e tau r_s2 rx" in subst)
   apply (cut_tac env="env" and x="x" and y="y" in cancel_add_rem_env)
    apply (auto)
  apply (rule_tac well_typed_add_vars)
   apply (cut_tac env="env" and x="x" and y="t" in partial_rem_add_env)
   apply (auto)
  done

lemma well_typed_contain_env: "\<lbrakk> contain_env env env'; well_typed env' r_s1 e tau r_s2 rx \<rbrakk> \<Longrightarrow> well_typed env r_s1 e tau r_s2 rx"
  apply (induct e arbitrary: env env' r_s1 tau r_s2 rx)
        apply (auto)
    (* var case *)
       apply (simp add: contain_env_def)
       apply (erule_tac x="deref_name x1a x2a" in allE)
       apply (auto)
      apply (simp add: contain_env_def)
      apply (erule_tac x="x1a" in allE)
      apply (auto)
    (* pair case *)
     apply (rule_tac x="r_s2a" in exI)
     apply (rule_tac x="r_s3" in exI)
     apply (rule_tac x="rx1" in exI)
     apply (auto)
     apply (rule_tac x="rx2" in exI)
     apply (auto)
    (* if case *)
    apply (rule_tac x="rx'" in exI)
    apply (rule_tac x="r_s2a" in exI)
    apply (auto)
    apply (rule_tac x="rx1" in exI)
    apply (auto)
    apply (rule_tac x="rx2" in exI)
    apply (auto)
    (* lam case *)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
   apply (rule_tac x="r_end" in exI)
   apply (rule_tac x="r_s'" in exI)
   apply (cut_tac r_s="env" and r_x="env'" and x="x1a" and t="t1" in dist_add_contain_env)
    apply (auto)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="r_s2a" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (rule_tac x="r_s3" in exI)
  apply (auto)
  done

    (*
      ####################################
        P5. well-typed manipulation for start permissions
      ####################################
    *)

lemma well_typed_comp_start_perm: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx \<rbrakk> \<Longrightarrow> well_typed env (comp_use_env r_s1 r_ex) e tau r_s2 rx"
  apply (induction e arbitrary: env r_s1 tau r_s2 rx)
        apply (auto)
    (* const, op, var case 1 *)
         apply (rule_tac comp_leq_use_env1)
         apply (simp)
        apply (rule_tac comp_leq_use_env1)
        apply (simp)
       apply (rule_tac comp_leq_use_env1)
       apply (simp)
    (* var case 2 *)
      apply (rule_tac x="r_exa" in exI)
      apply (auto)
       apply (rule_tac r_sb="diff_use_env r_s1 (comp_use_env (ereq_use_env x1a tau_x) r_exa)" in trans_leq_use_env)
        apply (rule_tac dist_diff_leq_use_env)
        apply (rule_tac self_comp_leq_use_env1)
       apply (auto)
      apply (rule_tac comp_leq_use_env1)
      apply (simp)
    (* pair case *)
     apply (rule_tac x="r_s2a" in exI)
     apply (rule_tac x="r_s3" in exI)
     apply (rule_tac x="rx1" in exI)
     apply (auto)
     apply (rule_tac x="rx2" in exI)
     apply (auto)
     apply (rule_tac x="r_exa" in exI)
     apply (auto)
     apply (rule_tac comp_leq_use_env1)
     apply (simp)
    (* if case *)
    apply (rule_tac x="rx'" in exI)
    apply (rule_tac x="r_s2a" in exI)
    apply (auto)
    (* lambda case *)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
    apply (rule_tac r_sb="r_s1" in trans_leq_use_env)
     apply (rule_tac comp_leq_use_env1)
     apply (rule_tac id_leq_use_env)
    apply (simp)
   apply (rule_tac x="r_exa" in exI)
   apply (auto)
    apply (rule_tac r_sb="diff_use_env r_s1 r_exa" in trans_leq_use_env)
     apply (rule_tac dist_diff_leq_use_env)
     apply (rule_tac self_comp_leq_use_env1)
    apply (simp)
   apply (rule_tac comp_leq_use_env1)
   apply (simp)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="r_s2a" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (rule_tac x="r_s3" in exI)
  apply (auto)
  apply (rule_tac x="r_exa" in exI)
  apply (auto)
  apply (rule_tac comp_leq_use_env1)
  apply (simp)
  done

lemma well_typed_comp_start_perm2: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx \<rbrakk> \<Longrightarrow> well_typed env (comp_use_env r_ex r_s1) e tau r_s2 rx"
  apply (cut_tac r_s="r_ex" and r_x="r_s1" in comm_comp_use_env)
  apply (auto)
  apply (rule_tac well_typed_comp_start_perm)
  apply (auto)
  done

lemma well_typed_incr_start_perm: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; leq_use_env r_s1 r_c \<rbrakk> \<Longrightarrow> well_typed env r_c e tau r_s2 rx"
  apply (cut_tac r_s="r_c" and r_x="r_s1" in cancel_comp_use_env2)
   apply (auto)
  apply (cut_tac env="env" and ?r_s1.0="r_s1" and r_ex="r_c" and e="e" and tau="tau" and ?r_s2.0="r_s2" and rx="rx" in well_typed_comp_start_perm2)
   apply (auto)
  done

    (*
      ####################################
        P6. well-typed manipulation for sweeping changes
      ####################################
    *)

    (* - diff perm lemmas *)

lemma wtdp_start_perm_req: "\<lbrakk> y \<notin> own_env_vars r_x; leq_use_env (req_use_env y tau) r_s1 \<rbrakk>
       \<Longrightarrow> leq_use_env (req_use_env y tau) (diff_use_env r_s1 r_x)"
  apply (rule_tac r_s="r_s1" in req_leq_use_env)
   apply (simp)
  apply (cut_tac r_s="r_s1" and x="y" and r_x="r_x" in diff_use_eq)
   apply (auto)
  apply (simp add: own_env_vars_def)
  done

lemma lhs_ddl_use_env: "\<lbrakk> disj_use_env r_s r_x \<rbrakk> \<Longrightarrow> leq_use_env (diff_use_env r_s (diff_use_env r_ex r_x)) (diff_use_env r_s r_ex)"
  apply (simp add: leq_use_env_def)
  apply (simp add: diff_use_env_def)
  apply (simp add: minus_use_env_def)
  apply (simp add: neg_use_env_def)
  apply (simp add: disj_use_env_def)
  apply (simp add: mini_disj_use_env_def)
  apply (auto)
  apply (erule_tac x="x" in allE)
  apply (erule_tac x="x" in allE)
  apply (auto)
  apply (case_tac "r_s x")
    apply (auto)
   apply (case_tac "r_ex x")
     apply (auto)
    apply (case_tac "r_x x")
      apply (auto)
   apply (case_tac "r_x x")
     apply (auto)
  apply (case_tac "r_s x")
    apply (auto)
   apply (case_tac "r_ex x")
     apply (auto)
  apply (case_tac "r_ex x")
    apply (auto)
  done

lemma weak_diff_req_use_env: "weak_use_env (diff_use_env (req_use_env x tau) (req_use_env x tau))"
  apply (simp add: diff_use_env_def)
  apply (simp add: minus_use_env_def)
  apply (simp add: neg_use_env_def)
  apply (simp add: weak_use_env_def)
  apply (auto)
  apply (case_tac "req_use_env x tau xa")
    apply (auto)
  done

lemma wtdp_disj_req_use_env2: "\<lbrakk> r_x x \<noteq> OwnPerm \<rbrakk> \<Longrightarrow> disj_use_env r_x (diff_use_env (req_use_env x tau) (req_use_env x tau))"
  apply (cut_tac x="x" and tau="tau" in weak_diff_req_use_env)
  apply (simp add: disj_use_env_def)
  apply (auto)
   apply (simp add: mini_disj_use_env_def)
   apply (auto)
   apply (rule_tac r_s="req_use_env x tau" in leq_use_none)
    apply (rule_tac self_diff_leq_use_env)
   apply (rule_tac req_use_none_alt)
   apply (auto)
  apply (simp add: mini_disj_use_env_def)
  apply (auto)
  apply (simp add: weak_use_env_def)
  done

lemma wtdp_end_req: "\<lbrakk> non_prim_vars env e \<inter> own_env_vars r_x = {}; x \<in> free_vars e; env x = Some tau;
  r_x x = OwnPerm \<rbrakk> \<Longrightarrow> end_req_perm tau = NoPerm"
  apply (case_tac "x \<in> non_prim_vars env e")
   apply (simp add: own_env_vars_def)
   apply (auto)
  apply (case_tac "req_type tau \<noteq> Prim")
   apply (simp add: non_prim_vars_def)
   apply (simp add: non_prim_entry_def)
  apply (simp add: end_req_perm_def)
  done

lemma well_typed_diff_perms: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; non_prim_vars env e \<inter> own_env_vars r_x = {} \<rbrakk> \<Longrightarrow>
  well_typed env (diff_use_env r_s1 r_x) e tau (diff_use_env r_s2 r_x) (diff_use_env rx r_x)"
  apply (induction e arbitrary: env r_s1 tau r_s2 rx r_x)
       apply (auto)
    (* const case *)
          apply (rule_tac dist_diff_leq_use_env)
          apply (simp)
         apply (rule_tac dist_diff_leq_use_env)
         apply (simp)
    (* op case *)
        apply (rule_tac dist_diff_leq_use_env)
        apply (simp)
       apply (rule_tac dist_diff_leq_use_env)
       apply (simp)
    (* var case p1. manipulation to show that x1a exists in r_s2 *)
      apply (rule_tac mini_disj_diff_leq_use_env2)
       apply (simp)
      apply (simp add: ereq_use_env_def)
      apply (simp add: mini_disj_use_env_def)
      apply (simp add: one_use_env_def)
      apply (auto)
      apply (rule_tac env="env" and e="VarExp x1a x2a" and r_x="r_x" and x="x1a" in wtdp_end_req)
         apply (auto)
    (* var case p2 *)
     apply (rule_tac x="diff_use_env r_ex r_x" in exI)
     apply (auto)
        apply (rule_tac rhs_fold_dcl_use_env)
        apply (rule_tac rhs_flip_use_env)
        apply (rule_tac rhs_pull_comp_use_env)
        apply (cut_tac r_ex="r_ex" and r_x="r_x" in sum_comp_diff_use_env)
        apply (auto)
        apply (rule_tac rhs_unroll_dcl_use_env)
        apply (rule_tac rhs_unroll_dcl_use_env)
        apply (rule_tac dist_diff_leq_use_env)
        apply (rule_tac rhs_fold_dcl_use_env)
        apply (simp)
       apply (rule_tac dist_diff_leq_use_env)
       apply (simp)
      apply (rule_tac dist_diff_leq_use_env)
      apply (simp)
    (* - use disjointess of r_x from (req x tau) to remove - r_x *)
     apply (rule_tac disj_diff_leq_use_env)
      apply (simp add: ereq_use_env_def)
      apply (simp add: disj_use_env_def)
      apply (auto)
       apply (rule_tac one_mini_disj_use_env1)
       apply (auto)
       apply (rule_tac env="env" and e="VarExp x1a x2a" and r_x="r_x" and x="x1a" in wtdp_end_req)
          apply (auto)
      apply (rule_tac one_mini_disj_use_env2)
      apply (auto)
      apply (simp add: comp_use_env_def)
      apply (simp add: one_use_env_def)
    (* - through a slightly more involved process we can also remove it from the left *)
     apply (rule_tac lhs_unroll_dcl_use_env)
     apply (rule_tac r_sb="diff_use_env (diff_use_env (ereq_use_env x1a tau_x) (ereq_use_env x1a tau_x)) r_ex" in trans_leq_use_env)
      apply (rule_tac lhs_fold_dcl_use_env)
      apply (simp)
     apply (rule_tac lhs_ddl_use_env)
     apply (rule_tac comm_disj_use_env)
     apply (simp add: ereq_use_env_def)
     apply (simp add: disj_use_env_def)
     apply (auto)
      apply (rule_tac one_mini_disj_use_env1)
      apply (auto)
      apply (rule_tac env="env" and e="VarExp x1a x2a" and r_x="r_x" and x="x1a" in wtdp_end_req)
         apply (auto)
     apply (rule_tac one_mini_disj_use_env2)
     apply (auto)
      apply (simp add: one_use_env_def)
    (* pair case *)
     apply (rule_tac x="diff_use_env r_s2a r_x" in exI)
     apply (rule_tac x="diff_use_env r_s3 r_x" in exI)
     apply (rule_tac x="diff_use_env rx1 r_x" in exI)
     apply (auto)
      apply (case_tac "\<not> non_prim_vars env e1 \<inter> own_env_vars r_x = {}")
       apply (simp add: non_prim_vars_def)
       apply (auto)
     apply (rule_tac x="diff_use_env rx2 r_x" in exI)
     apply (auto)
           apply (case_tac "\<not> non_prim_vars env e2 \<inter> own_env_vars r_x = {}")
            apply (simp add: non_prim_vars_def)
            apply (auto)
          (*apply (rule_tac aff_diff_use_env)
          apply (simp)*)
          apply (rule_tac t="lift_use_env (diff_use_env rx1 r_x) r" and s="diff_use_env (lift_use_env rx1 r) r_x" in subst)
           apply (rule_tac lift_diff_use_env)
          apply (rule_tac dist_diff_leq_use_env)
          apply (simp)
         apply (rule_tac t="lift_use_env (diff_use_env rx2 r_x) r" and s="diff_use_env (lift_use_env rx2 r) r_x" in subst)
          apply (rule_tac lift_diff_use_env)
         apply (rule_tac dist_diff_leq_use_env)
         apply (simp)
      apply (rule_tac r_s="lift_use_env rx1 r" in disj_leq_use_env1)
       apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
        apply (simp)
       apply (rule_tac dist_lift_leq_use_env)
       apply (rule_tac self_diff_leq_use_env)
      apply (rule_tac dist_lift_leq_use_env)
      apply (rule_tac self_diff_leq_use_env)
     apply (rule_tac x="diff_use_env r_ex r_x" in exI)
     apply (auto)
        apply (rule_tac t="diff_use_env (diff_use_env r_s3 r_x) (diff_use_env r_ex r_x)" and s="diff_use_env (diff_use_env r_s3 r_ex) r_x" in subst)
         apply (rule_tac dist_sq_diff_use_env)
        apply (rule_tac dist_diff_leq_use_env)
        apply (simp)
       apply (rule_tac dist_diff_leq_use_env)
       apply (simp)
      apply (rule_tac dist_diff_leq_use_env)
      apply (simp)
     apply (case_tac "req_type (PairTy t1 t2 r) = Prim")
      apply (simp add: pair_req_def)
      apply (auto)
      apply (rule_tac leq_empty_use_env)
     apply (simp add: pair_req_def)
     apply (rule_tac t="lift_use_env (diff_use_env rx1 r_x) r" and s="diff_use_env (lift_use_env rx1 r) r_x" in subst)
      apply (rule_tac lift_diff_use_env)
     apply (rule_tac t="lift_use_env (diff_use_env rx2 r_x) r" and s="diff_use_env (lift_use_env rx2 r) r_x" in subst)
      apply (rule_tac lift_diff_use_env)
     apply (simp add: dist_diff_comp_use_env)
     apply (rule_tac t="diff_use_env (diff_use_env (comp_use_env (lift_use_env rx1 r) (lift_use_env rx2 r)) r_x)
        (diff_use_env r_ex r_x)" and s="diff_use_env (diff_use_env (comp_use_env (lift_use_env rx1 r) (lift_use_env rx2 r)) r_ex) r_x" in subst)
      apply (rule_tac dist_sq_diff_use_env)
     apply (rule_tac dist_diff_leq_use_env)
     apply (simp)
    (* if case *)
    apply (rule_tac x="diff_use_env rx' r_x" in exI)
    apply (rule_tac x="diff_use_env r_s2a r_x" in exI)
    apply (auto)
     apply (case_tac "\<not> non_prim_vars env e1 \<inter> own_env_vars r_x = {}")
      apply (simp add: non_prim_vars_def)
      apply (auto)
    apply (rule_tac x="diff_use_env rx1 r_x" in exI)
    apply (auto)
     apply (case_tac "\<not> non_prim_vars env e2 \<inter> own_env_vars r_x = {}")
      apply (simp add: non_prim_vars_def)
      apply (auto)
    apply (rule_tac x="diff_use_env rx2 r_x" in exI)
    apply (auto)
     apply (case_tac "\<not> non_prim_vars env e3 \<inter> own_env_vars r_x = {}")
      apply (simp add: non_prim_vars_def)
      apply (auto)
    apply (simp add: diff_use_env_def)
    apply (rule_tac dist_minus_comp_use_env)
    (* lambda case *)
   apply (rule_tac x="diff_use_env rxa r_x" in exI)
   apply (auto)
      apply (rule_tac x="diff_use_env r_end (rem_use_env r_x x1a)" in exI)
      apply (rule_tac x="diff_use_env r_s' (rem_use_env r_x x1a)" in exI)
      apply (cut_tac r_s="rxa" and x="x1a" and r="r" and r_x="r_x" in diff_add_rem_use_env)
      apply (auto)
      apply (case_tac "\<not> non_prim_vars (add_env env x1a t1) e \<inter> own_env_vars (rem_use_env r_x x1a) = {}")
       apply (auto)
      apply (simp add: rem_use_env_def)
      apply (simp add: own_env_vars_def)
      apply (case_tac "x = x1a")
       apply (auto)
      apply (simp add: non_prim_vars_def)
      apply (simp add: non_prim_entry_def)
      apply (simp add: add_env_def)
      apply (auto)
     apply (rule_tac aff_diff_use_env)
     apply (simp)
    apply (rule_tac dist_diff_leq_use_env)
    apply (simp)
   apply (rule_tac x="diff_use_env r_ex r_x" in exI)
   apply (auto)
    (* - proving bounds *)
      apply (rule_tac t="diff_use_env (diff_use_env r_s1 r_x) (diff_use_env r_ex r_x)" and s="diff_use_env (diff_use_env r_s1 r_ex) r_x" in subst)
       apply (cut_tac r_s="r_s1" and r_x="r_ex" and r_ex="r_x" in dist_sq_diff_use_env)
       apply (auto)
      apply (rule_tac dist_diff_leq_use_env)
      apply (simp)
     apply (rule_tac dist_diff_leq_use_env)
     apply (simp)
    apply (rule_tac dist_diff_leq_use_env)
    apply (simp)
   apply (rule_tac t="diff_use_env (diff_use_env rxa r_x) (diff_use_env r_ex r_x)" and s="diff_use_env (diff_use_env rxa r_ex) r_x" in subst)
    apply (cut_tac r_s="rxa" and r_x="r_ex" and r_ex="r_x" in dist_sq_diff_use_env)
    apply (auto)
   apply (rule_tac dist_diff_leq_use_env)
   apply (simp)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="diff_use_env r_s2a r_x" in exI)
  apply (rule_tac x="diff_use_env rx1 r_x" in exI)
  apply (auto)
   apply (case_tac "\<not> non_prim_vars env e1 \<inter> own_env_vars r_x = {}")
    apply (simp add: non_prim_vars_def)
    apply (auto)
  apply (rule_tac x="diff_use_env rx2 r_x" in exI)
  apply (rule_tac x="diff_use_env r_s3 r_x" in exI)
  apply (auto)
   apply (case_tac "\<not> non_prim_vars env e2 \<inter> own_env_vars r_x = {}")
    apply (simp add: non_prim_vars_def)
    apply (auto)
    (* - reusable substitutions *)
  apply (case_tac "\<not> lift_use_env (diff_use_env rx2 r_x) r = diff_use_env (lift_use_env rx2 r) r_x")
   apply (cut_tac r_s="rx2" and r="r" and r_x="r_x" in lift_diff_use_env)
   apply (simp)
    (* - last instantiation *)
  apply (rule_tac x="diff_use_env r_ex r_x" in exI)
  apply (auto)
    (* - prove the bound for r_s2 *)
        apply (rule_tac rhs_fold_dcl_use_env)
        apply (rule_tac rhs_flip_use_env)
        apply (rule_tac rhs_unroll_dcl_use_env)
        apply (rule_tac rhs_diff_leq_use_env)
        apply (rule_tac r_sb="diff_use_env (diff_use_env r_s3 (comp_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_ex)) r_x" in trans_leq_use_env)
         apply (rule_tac lhs_fold_dcl_use_env)
         apply (rule_tac lhs_flip_use_env)
         apply (rule_tac lhs_unroll_dcl_use_env)
         apply (rule_tac unroll_dcl_use_env)
         apply (rule_tac dist_diff_leq_use_env_gen)
          apply (rule_tac dist_diff_leq_use_env_gen)
           apply (rule_tac self_diff_leq_use_env)
          apply (rule_tac dist_comp_leq_use_env)
           apply (rule_tac comp_leq_use_env1)
           apply (rule_tac self_diff_leq_use_env)
          apply (rule_tac comp_leq_use_env2)
          apply (rule_tac self_diff_leq_use_env)
         apply (rule_tac self_diff_leq_use_env)
        apply (rule_tac dist_diff_leq_use_env)
        apply (simp)
    (* - prove lift safety *)
    (* - prove rx1 + rx2 is subtractable *)
      apply (rule_tac r_sb="diff_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_x" in trans_leq_use_env)
       apply (rule_tac dist_diff_leq_use_env)
       apply (simp)
      apply (rule_tac dist_comp_leq_use_env)
       apply (rule_tac dist_diff_leq_use_env)
       apply (rule_tac self_comp_leq_use_env1)
      apply (rule_tac dist_diff_leq_use_env)
      apply (rule_tac self_comp_leq_use_env2)
    (* - prove disjointedness *)
     apply (rule_tac r_s="rx1" in disj_leq_use_env1)
      apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
       apply (simp)
      apply (rule_tac self_diff_leq_use_env)
     apply (rule_tac self_diff_leq_use_env)
    apply (rule_tac dist_diff_leq_use_env)
    apply (simp)
    (* - prove r_ex bound *)
   apply (rule_tac dist_diff_leq_use_env)
   apply (simp)
    (* - prove the bound for rx *)
  apply (simp add: app_req_def)
  apply (auto)
   apply (rule_tac leq_empty_use_env)
  apply (rule_tac t="comp_use_env (diff_use_env rx1 r_x) (diff_use_env rx2 r_x)" and s="diff_use_env (comp_use_env rx1 rx2) r_x" in subst)
   apply (simp add: diff_use_env_def)
   apply (rule_tac dist_minus_comp_use_env)
  apply (rule_tac t="comp_use_env (diff_use_env rx1 r_x) (diff_use_env (lift_use_env rx2 r) r_x)" and
      s="diff_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_x" in subst)
   apply (simp add: diff_use_env_def)
   apply (rule_tac dist_minus_comp_use_env)
  apply (rule_tac t="comp_use_env (diff_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_x) (diff_use_env r_ex r_x)" and
      s="diff_use_env (comp_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_ex) r_x" in subst)
   apply (simp add: diff_use_env_def)
   apply (rule_tac dist_minus_comp_use_env)
  apply (rule_tac t="diff_use_env (diff_use_env (comp_use_env rx1 rx2) r_x) (diff_use_env (comp_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_ex) r_x)" and
      s="diff_use_env (diff_use_env (comp_use_env rx1 rx2) (comp_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_ex)) r_x" in subst)
   apply (rule_tac dist_sq_diff_use_env)
  apply (rule_tac dist_diff_leq_use_env)
  apply (simp)
  done

lemma well_typed_rem_perms: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; x \<notin> non_prim_vars env e \<rbrakk> \<Longrightarrow>
  well_typed env (rem_use_env r_s1 x) e tau (rem_use_env r_s2 x) (rem_use_env rx x)"
  apply (cut_tac r_s="r_s1" and x="x" in diff_rem_use_env)
  apply (cut_tac r_s="r_s2" and x="x" in diff_rem_use_env)
  apply (cut_tac r_s="rx" and x="x" in diff_rem_use_env)
  apply (auto)
  apply (rule_tac well_typed_diff_perms)
   apply (auto)
  apply (simp add: one_use_env_def)
  apply (simp add: own_env_vars_def)
  apply (case_tac "x = xa")
   apply (auto)
  done

lemma well_typed_add_perms_rev: "\<lbrakk> well_typed env (add_use_env r_s1 x r) e tau (add_use_env r_s2 x r') (add_use_env rx x r3);
  r_s1 x = NoPerm; r_s2 x = NoPerm; rx x = NoPerm; x \<notin> non_prim_vars env e \<rbrakk> \<Longrightarrow> well_typed env r_s1 e tau r_s2 rx"
  apply (cut_tac r_s="r_s1" and x="x" and r="r" in cancel_rem_add_use_env)
   apply (auto)
  apply (cut_tac r_s="r_s2" and x="x" and r="r'" in cancel_rem_add_use_env)
   apply (auto)
  apply (cut_tac r_s="rx" and x="x" and r="r3" in cancel_rem_add_use_env)
   apply (auto)
  apply (cut_tac env="env" and ?r_s1.0="add_use_env r_s1 x r" and e="e" and tau="tau" and ?r_s2.0="add_use_env r_s2 x r'" and rx="add_use_env rx x r3" and x="x" in well_typed_rem_perms)
    apply (auto)
  done

    (*
      ####################################
        P7. well-typed manipulation for permission changes
      ####################################
    *)

lemma well_typed_comp_perms_gen: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; mini_disj_use_env r_s1 r_ex \<rbrakk> \<Longrightarrow>
  well_typed env (comp_use_env r_s1 r_ex) e tau (comp_use_env r_s2 r_ex) rx"
  apply (induct e arbitrary: env r_s1 tau r_s2 rx)
       apply (auto)
    (* const case *)
           apply (rule_tac dist_comp_leq_use_env)
            apply (rule_tac comp_leq_use_env1)
            apply (simp)
           apply (rule_tac comp_leq_use_env2)
           apply (rule_tac id_leq_use_env)
          apply (rule_tac comp_leq_use_env1)
          apply (simp)
    (* op case *)
         apply (rule_tac dist_comp_leq_use_env)
          apply (rule_tac comp_leq_use_env1)
          apply (simp)
         apply (rule_tac comp_leq_use_env2)
         apply (rule_tac id_leq_use_env)
        apply (rule_tac comp_leq_use_env1)
        apply (simp)
    (* var case *)
       apply (rule_tac comp_leq_use_env1)
       apply (simp)
      apply (rule_tac x="r_exa" in exI)
      apply (auto)
    (* - first half of end permission bounds check *)
        apply (rule_tac dist_comp_leq_use_env)
         apply (rule_tac r_sb="diff_use_env r_s1 (comp_use_env (ereq_use_env x1a tau_x) r_exa)" in trans_leq_use_env)
          apply (rule_tac dist_diff_leq_use_env)
          apply (rule_tac self_comp_leq_use_env1)
         apply (simp)
    (* - second half of end permission bounds check *)
        apply (rule_tac rhs_dist_dcl_use_env)
        apply (rule_tac comp_leq_use_env2)
        apply (rule_tac mini_disj_diff_leq_use_env)
         apply (rule_tac id_leq_use_env)
        apply (rule_tac r_s="r_s1" in mini_disj_leq_use_env1)
         apply (simp)
        apply (rule_tac dist_comp_leq_use_env)
         apply (auto)
    (* - various bounds checks *)
       apply (rule_tac comp_leq_use_env1)
       apply (simp)
      apply (rule_tac comp_leq_use_env1)
      apply (simp)
    (* pair case *)
     apply (rule_tac x="comp_use_env r_s2a r_ex" in exI)
     apply (rule_tac x="comp_use_env r_s3 r_ex" in exI)
     apply (rule_tac x="rx1" in exI)
     apply (auto)
     apply (rule_tac x="rx2" in exI)
     apply (auto)
        apply (cut_tac r_x="r_s2a" and r_s="r_s1" and r_ex="r_ex" in mini_disj_leq_use_env1)
          apply (simp)
         apply (rule_tac well_typed_perm_leq)
         apply (auto)
       apply (rule_tac comp_leq_use_env1)
       apply (simp)
      apply (rule_tac comp_leq_use_env1)
      apply (simp)
     apply (rule_tac x="r_exa" in exI)
     apply (auto)
       apply (rule_tac rhs_dist_dcl_use_env)
       apply (rule_tac dist_comp_leq_use_env)
        apply (rule_tac comp_leq_use_env1)
        apply (simp)
       apply (rule_tac comp_leq_use_env2)
       apply (rule_tac mini_disj_diff_leq_use_env)
        apply (rule_tac id_leq_use_env)
       apply (rule_tac r_s="r_s1" in mini_disj_leq_use_env1)
        apply (simp_all)
      apply (rule_tac comp_leq_use_env1)
      apply (simp)
     apply (rule_tac comp_leq_use_env1)
     apply (simp)
    (* if case *)
    apply (rule_tac x="rx'" in exI)
    apply (rule_tac x="comp_use_env r_s2a r_ex" in exI)
    apply (auto)
    apply (cut_tac r_s="r_s1" and r_x="r_s2a" and r_ex="r_ex" in mini_disj_leq_use_env1)
      apply (simp)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    apply (rule_tac x="rx1" in exI)
    apply (auto)
    apply (rule_tac x="rx2" in exI)
    apply (auto)
    (* lambda case *)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
    apply (rule_tac comp_leq_use_env1)
    apply (simp)
   apply (rule_tac x="r_exa" in exI)
   apply (auto)
     apply (rule_tac rhs_dist_dcl_use_env)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac comp_leq_use_env1)
      apply (simp)
     apply (rule_tac comp_leq_use_env2)
     apply (rule_tac mini_disj_diff_leq_use_env)
      apply (rule_tac id_leq_use_env)
     apply (rule_tac r_s="r_s1" in mini_disj_leq_use_env1)
      apply (auto)
    apply (rule_tac comp_leq_use_env1)
    apply (simp)
   apply (rule_tac comp_leq_use_env1)
   apply (simp)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="comp_use_env r_s2a r_ex" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (rule_tac x="comp_use_env r_s3 r_ex" in exI)
  apply (auto)
   apply (cut_tac r_s="r_s1" and r_x="r_s2a" and r_ex="r_ex" in mini_disj_leq_use_env1)
     apply (simp)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
  apply (cut_tac r_sa="r_s1" and r_sb="r_s2a" and r_sc="r_s3" in trans_leq_use_env)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
   apply (rule_tac well_typed_perm_leq)
   apply (auto)
  apply (rule_tac x="r_exa" in exI)
  apply (auto)
    (* - first half of end permissions bounds check *)
     apply (rule_tac rhs_dist_dcl_use_env)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac comp_leq_use_env1)
      apply (simp)
    (* - second half of end permissions bounds check *)
     apply (rule_tac comp_leq_use_env2)
     apply (rule_tac mini_disj_diff_leq_use_env)
      apply (rule_tac id_leq_use_env)
     apply (rule_tac r_s="r_s1" in mini_disj_leq_use_env1)
      apply (simp)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
       apply (auto)
    (* - final bounds checks *)
    apply (rule_tac comp_leq_use_env1)
    apply (simp)
   apply (rule_tac comp_leq_use_env1)
   apply (simp)
  apply (rule_tac comp_leq_use_env1)
  apply (simp)
  done

lemma well_typed_comp_perms: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; disj_use_env r_s1 r_ex \<rbrakk> \<Longrightarrow>
  well_typed env (comp_use_env r_s1 r_ex) e tau (comp_use_env r_s2 r_ex) rx"
  apply (rule_tac well_typed_comp_perms_gen)
   apply (simp)
  apply (simp add: disj_use_env_def)
  done

    (*
lemma well_typed_comp_perms: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; disj_use_env r_s1 r_ex \<rbrakk> \<Longrightarrow>
  well_typed env (comp_use_env r_s1 r_ex) e tau (comp_use_env r_s2 r_ex) rx"
  apply (induct e arbitrary: env r_s1 tau r_s2 rx)
       apply (auto)
    (* const case *)
          apply (rule_tac dist_comp_leq_use_env)
           apply (rule_tac comp_leq_use_env1)
           apply (simp)
          apply (rule_tac comp_leq_use_env2)
          apply (rule_tac id_leq_use_env)
         apply (rule_tac comp_leq_use_env1)
         apply (simp)
    (* op case *)
        apply (rule_tac dist_comp_leq_use_env)
         apply (rule_tac comp_leq_use_env1)
         apply (simp)
        apply (rule_tac comp_leq_use_env2)
        apply (rule_tac id_leq_use_env)
       apply (rule_tac comp_leq_use_env1)
       apply (simp)
    (* var case *)
      apply (rule_tac comp_leq_use_env1)
      apply (simp)
     apply (rule_tac x="r_exa" in exI)
     apply (auto)
    (* - first half of end permission bounds check *)
       apply (rule_tac dist_comp_leq_use_env)
        apply (rule_tac r_sb="diff_use_env r_s1 (comp_use_env (req_use_env x1a tau) r_exa)" in trans_leq_use_env)
         apply (rule_tac dist_diff_leq_use_env)
         apply (rule_tac self_comp_leq_use_env1)
        apply (simp)
    (* - second half of end permission bounds check *)
       apply (rule_tac disj_diff_leq_use_env)
        apply (rule_tac r_s="r_s1" in disj_leq_use_env1)
         apply (simp)
        apply (rule_tac dist_comp_leq_use_env)
         apply (auto)
    (* - various bounds checks *)
       apply (rule_tac self_comp_leq_use_env2)
      apply (rule_tac comp_leq_use_env1)
      apply (simp)
     apply (rule_tac comp_leq_use_env1)
     apply (simp)
    (* if case *)
    apply (rule_tac x="rx'" in exI)
    apply (rule_tac x="comp_use_env r_s2a r_ex" in exI)
    apply (auto)
    apply (cut_tac r_s="r_s1" and r_x="r_s2a" and r_ex="r_ex" in disj_leq_use_env1)
      apply (simp)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    apply (rule_tac x="rx1" in exI)
    apply (auto)
    apply (rule_tac x="rx2" in exI)
    apply (auto)
    (* lambda case *)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
    apply (rule_tac comp_leq_use_env1)
    apply (simp)
   apply (rule_tac x="r_exa" in exI)
   apply (auto)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac r_sb="diff_use_env r_s1 r_exa" in trans_leq_use_env)
      apply (rule_tac dist_diff_leq_use_env)
      apply (rule_tac self_comp_leq_use_env1)
     apply (simp)
    apply (rule_tac disj_diff_leq_use_env)
     apply (rule_tac r_s="r_s1" in disj_leq_use_env1)
       apply (auto)
     apply (rule_tac self_comp_leq_use_env2)
    apply (rule_tac comp_leq_use_env1)
    apply (simp)
   apply (rule_tac comp_leq_use_env1)
   apply (simp)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="comp_use_env r_s2a r_ex" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (rule_tac x="comp_use_env r_s3 r_ex" in exI)
  apply (auto)
   apply (cut_tac r_s="r_s1" and r_x="r_s2a" and r_ex="r_ex" in disj_leq_use_env1)
     apply (simp)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
  apply (cut_tac r_sa="r_s1" and r_sb="r_s2a" and r_sc="r_s3" in trans_leq_use_env)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
   apply (rule_tac well_typed_perm_leq)
   apply (auto)
  apply (rule_tac x="r_exa" in exI)
  apply (auto)
    (* - first half of end permissions bounds check *)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac r_sb="diff_use_env r_s3 (comp_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_exa)" in trans_leq_use_env)
       apply (rule_tac dist_diff_leq_use_env)
       apply (rule_tac self_comp_leq_use_env1)
      apply (simp)
    (* - second half of end permissions bounds check *)
     apply (rule_tac disj_diff_leq_use_env)
      apply (rule_tac r_s="r_s1" in disj_leq_use_env1)
       apply (simp)
      apply (rule_tac dist_comp_leq_use_env)
       apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
        apply (auto)
    (* - final bounds checks *)
     apply (rule_tac self_comp_leq_use_env2)
    apply (rule_tac comp_leq_use_env1)
    apply (simp)
   apply (rule_tac comp_leq_use_env1)
   apply (simp)
  apply (rule_tac comp_leq_use_env1)
  apply (simp)
  done*)

lemma well_typed_comp_perms2: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; disj_use_env r_s1 r_ex \<rbrakk> \<Longrightarrow>
  well_typed env (comp_use_env r_ex r_s1) e tau (comp_use_env r_ex r_s2) rx"
  apply (cut_tac r_s="r_ex" and r_x="r_s1" in comm_comp_use_env)
  apply (cut_tac r_s="r_ex" and r_x="r_s2" in comm_comp_use_env)
  apply (auto)
  apply (rule_tac well_typed_comp_perms)
   apply (auto)
  done

lemma well_typed_add_perms: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; x \<notin> non_prim_vars env e; r = OwnPerm; rx x = NoPerm \<rbrakk> \<Longrightarrow>
  well_typed env (add_use_env r_s1 x r) e tau (add_use_env r_s2 x r) rx"
  apply (cut_tac r_s="r_s1" and x="x" and r="r" in partial_add_rem_use_env)
  apply (cut_tac r_s="r_s2" and x="x" and r="r" in partial_add_rem_use_env)
  apply (cut_tac r_s="rx" and x="x" in ignore_rem_use_env)
   apply (simp)
  apply (cut_tac r_s="rem_use_env r_s1 x" and x="x" and r="r" in add_comp_use_env)
   apply (auto)
  apply (cut_tac r_s="rem_use_env r_s2 x" and x="x" and r="r" in add_comp_use_env)
    apply (auto)
  apply (rule_tac well_typed_comp_perms)
   apply (cut_tac env="env" and ?r_s1.0="r_s1" and e="e" and tau="tau" and ?r_s2.0="r_s2" and rx="rx" and x="x" in well_typed_rem_perms)
     apply (auto)
  apply (rule_tac disj_one_use_env)
  apply (simp add: rem_use_env_def)
  done

   (*
lemma well_typed_add_perms: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; x \<notin> free_vars e; r = OwnPerm; rx x = NoPerm \<rbrakk> \<Longrightarrow>
  well_typed env (add_use_env r_s1 x r) e tau (add_use_env r_s2 x r) rx"
  apply (cut_tac r_s="r_s1" and x="x" and r="r" in partial_add_rem_use_env)
  apply (cut_tac r_s="r_s2" and x="x" and r="r" in partial_add_rem_use_env)
  apply (cut_tac r_s="rx" and x="x" in ignore_rem_use_env)
   apply (simp)
  apply (cut_tac r_s="rem_use_env r_s1 x" and x="x" and r="r" in add_comp_use_env)
   apply (auto)
  apply (cut_tac r_s="rem_use_env r_s2 x" and x="x" and r="r" in add_comp_use_env)
    apply (auto)
  apply (rule_tac well_typed_comp_perms)
   apply (cut_tac env="env" and ?r_s1.0="r_s1" and e="e" and tau="tau" and ?r_s2.0="r_s2" and rx="rx" and x="x" in well_typed_rem_perms)
     apply (auto)
  apply (rule_tac disj_one_use_env)
  apply (simp add: rem_use_env_def)
  done    *)

lemma well_typed_incr_simul_perm: "\<lbrakk> leq_use_env r_s r_c; well_typed env r_s e tau r_s rx \<rbrakk> \<Longrightarrow> well_typed env r_c e tau r_c rx"
  apply (rule_tac t="r_c" and s="comp_use_env r_s (diff_use_env r_c r_s)" in subst)
   apply (rule_tac msum_diff_comp_use_env)
   apply (simp)
  apply (rule_tac well_typed_comp_perms_gen)
   apply (simp)
  apply (rule_tac mini_disj_diff_use_env)
  done

lemma well_typed_lift_perms: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx \<rbrakk> \<Longrightarrow> well_typed env (lift_use_env r_s1 r) e tau (lift_use_env r_s2 r) rx"
  apply (induct e arbitrary: env r_s1 tau r_s2 rx)
        apply (auto)
    (* const + op cases *)
           apply (rule_tac dist_lift_leq_use_env)
           apply (simp)
          apply (rule_tac lift_leq_use_env)
          apply (simp)
         apply (rule_tac dist_lift_leq_use_env)
         apply (simp)
        apply (rule_tac lift_leq_use_env)
        apply (simp)
    (* var cases *)
       apply (rule_tac lift_leq_use_env)
       apply (simp)
      apply (rule_tac x="r_ex" in exI)
      apply (auto)
        apply (cut_tac r_s="r_s1" and r_x="comp_use_env (ereq_use_env x1a tau_x) r_ex" and r="r" in lift_diff_use_env)
        apply (auto)
        apply (rule_tac dist_lift_leq_use_env)
        apply (simp)
       apply (rule_tac lift_leq_use_env)
       apply (simp)
      apply (rule_tac lift_leq_use_env)
      apply (simp)
    (* pair case *)
     apply (rule_tac x="lift_use_env r_s2a r" in exI)
     apply (rule_tac x="lift_use_env r_s3 r" in exI)
     apply (rule_tac x="rx1" in exI)
     apply (auto)
     apply (rule_tac x="rx2" in exI)
     apply (auto)
       apply (rule_tac lift_leq_use_env)
       apply (simp)
      apply (rule_tac lift_leq_use_env)
      apply (simp)
     apply (rule_tac x="r_ex" in exI)
     apply (auto)
       apply (cut_tac r_s="r_s3" and r_x="r_ex" and r="r" in lift_diff_use_env)
       apply (simp)
       apply (rule_tac dist_lift_leq_use_env)
       apply (simp)
      apply (rule_tac lift_leq_use_env)
      apply (simp)
     apply (rule_tac lift_leq_use_env)
     apply (simp)
    (* if case *)
    apply (rule_tac x="rx'" in exI)
    apply (rule_tac x="lift_use_env r_s2a r" in exI)
    apply (auto)
    apply (rule_tac x="rx1" in exI)
    apply (auto)
    apply (rule_tac x="rx2" in exI)
    apply (auto)
    (* lam case *)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
    apply (rule_tac lift_leq_use_env)
    apply (simp)
   apply (rule_tac x="r_ex" in exI)
   apply (auto)
     apply (cut_tac r_s="r_s1" and r_x="r_ex" and r="r" in lift_diff_use_env)
     apply (auto)
     apply (rule_tac dist_lift_leq_use_env)
     apply (simp)
    apply (rule_tac lift_leq_use_env)
    apply (simp)
   apply (rule_tac lift_leq_use_env)
   apply (simp)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="ra" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="lift_use_env r_s2a r" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (rule_tac x="lift_use_env r_s3 r" in exI)
  apply (auto)
  apply (rule_tac x="r_ex" in exI)
  apply (auto)
     apply (cut_tac r_s="r_s3" and r_x="comp_use_env (comp_use_env rx1 (lift_use_env rx2 ra)) r_ex" and r="r" in lift_diff_use_env)
     apply (auto)
     apply (rule_tac dist_lift_leq_use_env)
     apply (simp)
    apply (rule_tac lift_leq_use_env)
    apply (simp)
   apply (rule_tac lift_leq_use_env)
   apply (simp)
  apply (rule_tac lift_leq_use_env)
  apply (simp)
  done

    (*
      ####################################
        P8. well-typed manipulation for end permissions
      ####################################
    *)

lemma wtdep_diff_use_env: "\<lbrakk> leq_use_env r_x (diff_use_env r_s r_xa) \<rbrakk> \<Longrightarrow> diff_use_env r_x r_ex = diff_use_env r_x (comp_use_env (diff_use_env r_ex r_xa) r_xa)"
  apply (case_tac "\<forall> x. diff_use_env r_x r_ex x = diff_use_env r_x (comp_use_env (diff_use_env r_ex r_xa) r_xa) x")
   apply (auto)
  apply (simp add: diff_use_env_def)
  apply (simp add: minus_use_env_def)
  apply (simp add: neg_use_env_def)
  apply (simp add: leq_use_env_def)
  apply (simp add: comp_use_env_def)
  apply (erule_tac x="x" in allE)
  apply (case_tac "r_x x")
    apply (auto)
   apply (case_tac "r_s x")
     apply (auto)
    apply (case_tac "r_xa x")
      apply (auto)
     apply (case_tac "r_ex x")
       apply (auto)
    apply (case_tac "r_ex x")
      apply (auto)
   apply (case_tac "r_xa x")
     apply (auto)
    apply (case_tac "r_ex x")
      apply (auto)
   apply (case_tac "r_ex x")
     apply (auto)
  apply (case_tac "r_s x")
    apply (auto)
   apply (case_tac "r_xa x")
     apply (auto)
  apply (case_tac "r_xa x")
    apply (auto)
   apply (case_tac "r_ex x")
     apply (auto)
  apply (case_tac "r_ex x")
    apply (auto)
  done

lemma wtdep_strong_use_vars: "\<lbrakk> well_typed env (diff_use_env r_s1 r_x) e tau r_s2 rx; strong_use_env r_x \<rbrakk> \<Longrightarrow> non_prim_vars env e \<inter> own_env_vars r_x = {}"
  apply (auto)
  apply (case_tac "r_x x \<noteq> NoPerm")
   apply (case_tac "r_x x")
     apply (auto)
    apply (simp add: strong_use_env_def)
   apply (cut_tac r_s="r_s1" and r_ex="r_x" and x="x" in diff_use_none_ex)
    apply (auto)
   apply (cut_tac x="x" and e="e" and env="env" and ?r_s1.0="diff_use_env r_s1 r_x" in well_typed_no_npv_use)
     apply (auto)
  apply (simp add: own_env_vars_def)
  done

lemma well_typed_break: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx \<rbrakk> \<Longrightarrow> well_typed env r_s1 e tau (norm_use_env r_s1 r_s2) rx"
  apply (induct e arbitrary: env r_s1 tau r_s2 rx)
        apply (auto)
    (* const case *)
          apply (rule_tac self_norm_leq_use_env)
         apply (rule_tac rhs_norm_leq_use_env)
          apply (auto)
    (* op case *)
        apply (rule_tac self_norm_leq_use_env)
       apply (rule_tac rhs_norm_leq_use_env)
        apply (auto)
    (* var case *)
      apply (rule_tac x="r_ex" in exI)
      apply (auto)
       apply (rule_tac diff_norm_leq_use_env)
       apply (simp)
      apply (rule_tac rhs_norm_leq_use_env)
       apply (simp)
      apply (rule_tac r_sb="diff_use_env r_s1 (comp_use_env (ereq_use_env x1a tau_x) r_ex)" in trans_leq_use_env)
       apply (rule_tac self_diff_leq_use_env)
      apply (auto)
    (* pair case *)
     apply (cut_tac r_sc="r_s3" and r_sb="r_s2a" and r_sa="r_s1" in trans_leq_use_env)
       apply (rule_tac well_typed_perm_leq)
       apply (auto)
      apply (rule_tac well_typed_perm_leq)
      apply (auto)
     apply (rule_tac x="norm_use_env r_s1 r_s2a" in exI)
     apply (rule_tac x="norm_use_env r_s1 r_s3" in exI)
     apply (rule_tac x="rx1" in exI)
     apply (auto)
     apply (rule_tac x="rx2" in exI)
     apply (auto)
        apply (rule_tac t="norm_use_env r_s1 r_s3" and s="norm_use_env (norm_use_env r_s1 r_s2a) r_s3" in subst)
         apply (rule_tac sub_norm_use_env)
         apply (rule_tac well_typed_perm_leq)
         apply (auto)
        apply (cut_tac env="env" and ?r_s1.0="r_s2a" and r_c="norm_use_env r_s1 r_s2a" and e="e2" and ?r_s2.0="r_s3" and rx="rx2" in well_typed_incr_start_perm)
          apply (auto)
        apply (rule_tac rhs_self_norm_leq_use_env)
        apply (rule_tac well_typed_perm_leq)
        apply (auto)
       apply (rule_tac rhs_norm_leq_use_env)
        apply (auto)
      apply (rule_tac rhs_norm_leq_use_env)
       apply (auto)
     apply (rule_tac x="r_ex" in exI)
     apply (auto)
      apply (rule_tac spec_norm_leq_use_env)
      apply (simp)
     apply (rule_tac rhs_norm_leq_use_env)
      apply (simp)
     apply (rule_tac r_sb="diff_use_env r_s3 r_ex" in trans_leq_use_env)
      apply (rule_tac diff_leq_use_env)
     apply (auto)
    (* if case *)
    apply (rule_tac x="rx'" in exI)
    apply (rule_tac x="norm_use_env r_s1 r_s2a" in exI)
    apply (auto)
    (* - common substitution *)
    apply (cut_tac ?r_s1.0="r_s2a" and ?r_s2.0="r_s2" in well_typed_perm_leq)
     apply (auto)
    apply (rule_tac t="norm_use_env r_s1 r_s2" and s="norm_use_env (norm_use_env r_s1 r_s2a) r_s2" in subst)
     apply (rule_tac sub_norm_use_env)
     apply (simp)
    (* - rx1 *)
    apply (rule_tac x="rx1" in exI)
    apply (auto)
     apply (cut_tac env="env" and ?r_s1.0="r_s2a" and r_c="norm_use_env r_s1 r_s2a" and e="e2" and ?r_s2.0="r_s2" and rx="rx1" in well_typed_incr_start_perm)
       apply (auto)
     apply (rule_tac rhs_self_norm_leq_use_env)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    (* - rx2 *)
    apply (rule_tac x="rx2" in exI)
    apply (auto)
    apply (cut_tac env="env" and ?r_s1.0="r_s2a" and r_c="norm_use_env r_s1 r_s2a" and e="e3" and ?r_s2.0="r_s2" and rx="rx2" in well_typed_incr_start_perm)
      apply (auto)
    apply (rule_tac rhs_self_norm_leq_use_env)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
    (* lam case *)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
   apply (rule_tac x="r_ex" in exI)
   apply (auto)
    apply (rule_tac diff_norm_leq_use_env)
    apply (simp)
   apply (rule_tac rhs_norm_leq_use_env)
    apply (auto)
   apply (rule_tac r_sb="diff_use_env r_s1 r_ex" in trans_leq_use_env)
    apply (rule_tac self_diff_leq_use_env)
   apply (auto)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="norm_use_env r_s1 r_s2a" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (rule_tac x="norm_use_env r_s1 r_s3" in exI)
  apply (cut_tac ?r_s1.0="r_s2a" and ?r_s2.0="r_s3" in well_typed_perm_leq)
   apply (auto)
   apply (rule_tac t="norm_use_env r_s1 r_s3" and s="norm_use_env (norm_use_env r_s1 r_s2a) r_s3" in subst)
    apply (rule_tac sub_norm_use_env)
    apply (simp)
   apply (cut_tac env="env" and ?r_s1.0="r_s2a" and r_c="norm_use_env r_s1 r_s2a" and e="e2" and ?r_s2.0="r_s3" and rx="rx2" in well_typed_incr_start_perm)
     apply (auto)
   apply (rule_tac rhs_self_norm_leq_use_env)
   apply (rule_tac well_typed_perm_leq)
   apply (auto)
  apply (cut_tac r_sc="r_s3" and r_sb="r_s2a" and r_sa="r_s1" in trans_leq_use_env)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
  apply (rule_tac x="r_ex" in exI)
  apply (auto)
    apply (rule_tac spec_norm_leq_use_env)
    apply (simp)
   apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
    apply (rule_tac rhs_self_norm_leq_use_env)
    apply (auto)
  apply (rule_tac r_sb="r_s2" in trans_leq_use_env)
   apply (rule_tac rhs_self_norm_leq_use_env)
   apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
    apply (auto)
  apply (rule_tac r_sb="diff_use_env r_s3 (comp_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_ex)" in trans_leq_use_env)
   apply (rule_tac self_diff_leq_use_env)
  apply (simp)
  done

    (* when we perform substitution, we need to be able to stop "requiring" permissions. the
    intuition behind this lemma is that we no longer need a permission if we simply remove it from
    the list of permissions in the environment. *)

lemma well_typed_diff_end_perm: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; leq_use_env r_ex r_s1 \<rbrakk> \<Longrightarrow>
  well_typed env r_s1 e tau (diff_use_env r_s2 r_ex) (diff_use_env rx r_ex)"
  apply (induct e arbitrary: env r_s1 tau r_s2 rx r_ex)
        apply (auto)
    (* const case + op case are trivial since they never require permissions *)
          apply (rule_tac diff_leq_use_env)
          apply (simp)
         apply (rule_tac dist_diff_leq_use_env)
         apply (simp)
        apply (rule_tac diff_leq_use_env)
        apply (simp)
       apply (rule_tac dist_diff_leq_use_env)
       apply (simp)
    (* var case *)
      apply (rule_tac x="comp_use_env r_exa r_ex" in exI)
      apply (auto)
         apply (rule_tac rhs_unroll_dcl_use_env)
         apply (rule_tac rhs_unroll_dcl_use_env)
         apply (rule_tac dist_diff_leq_use_env)
         apply (rule_tac rhs_fold_dcl_use_env)
         apply (simp)
        apply (rule_tac dist_diff_leq_use_env)
        apply (simp)
       apply (rule_tac dist_comp_leq_use_env)
        apply (auto)
      apply (rule_tac lhs_unroll_dcl_use_env)
      apply (rule_tac lhs_unroll_dcl_use_env)
      apply (rule_tac dist_diff_leq_use_env)
      apply (rule_tac lhs_fold_dcl_use_env)
      apply (simp)
    (* pair case *)
     apply (rule_tac x="r_s2a" in exI)
     apply (rule_tac x="r_s3" in exI)
     apply (rule_tac x="rx1" in exI)
     apply (auto)
     apply (rule_tac x="rx2" in exI)
     apply (auto)
     apply (rule_tac x="comp_use_env r_exa r_ex" in exI)
     apply (auto)
        apply (rule_tac rhs_unroll_dcl_use_env)
        apply (rule_tac dist_diff_leq_use_env)
        apply (simp)
       apply (rule_tac dist_diff_leq_use_env)
       apply (simp)
      apply (rule_tac dist_comp_leq_use_env)
       apply (simp_all)
     apply (case_tac "req_type (PairTy t1 t2 r) = Prim")
      apply (simp add: pair_req_def)
      apply (rule_tac leq_empty_use_env)
     apply (simp add: pair_req_def)
     apply (rule_tac lhs_unroll_dcl_use_env)
     apply (rule_tac dist_diff_leq_use_env)
     apply (simp)
    (* if case *)
    apply (rule_tac x="rx'" in exI)
    apply (cut_tac env="env" and ?r_s1.0="r_s1" and e="e1" and ?r_s2.0="r_s2a" in well_typed_break)
     apply (auto)
    apply (cut_tac r_x="r_s2a" and r_s="r_s1" in ex_norm_use_env)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    (* - setup r_s2 \<le> r_s1 - r_exa *)
    apply (cut_tac r_sc="r_s2" and r_sb="r_s2a" and r_sa="norm_use_env r_s1 r_s2a" in trans_leq_use_env)
      apply (rule_tac rhs_self_norm_leq_use_env)
      apply (rule_tac well_typed_perm_leq)
      apply (auto)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    (* - prelim for both inductions *)
    apply (case_tac "diff_use_env r_s2 (comp_use_env (diff_use_env r_ex r_exa) r_exa) \<noteq> diff_use_env (diff_use_env r_s2 (diff_use_env r_ex r_exa)) r_exa")
     apply (cut_tac r_s="r_s2" and r_x="diff_use_env r_ex r_exa" and r_ex="r_exa" in diff_comp_use_env)
     apply (auto)
    apply (cut_tac r_sc="diff_use_env r_ex r_exa" and r_sb="r_ex" and r_sa="r_s1" in trans_leq_use_env)
      apply (simp)
     apply (rule_tac self_diff_leq_use_env)
    (* - first induction *)
    apply (rule_tac x="diff_use_env r_s1 r_exa" in exI)
    apply (auto)
    apply (rule_tac x="diff_use_env rx1 r_ex" in exI)
    apply (auto)
    apply (cut_tac r_x="r_s2" and r_s="r_s1" and r_xa="r_exa" and r_ex="r_ex" in wtdep_diff_use_env)
     apply (auto)
    apply (cut_tac r_x="rx1" and r_s="r_s1" and r_xa="r_exa" and r_ex="r_ex" in wtdep_diff_use_env)
      apply (auto)
      apply (rule_tac r_sb="r_s2" in trans_leq_use_env)
       apply (simp)
      apply (rule_tac well_typed_perm_leqx)
      apply (auto)
     apply (rule_tac t="diff_use_env rx1 (comp_use_env (diff_use_env r_ex r_exa) r_exa)" and s="diff_use_env (diff_use_env rx1 (diff_use_env r_ex r_exa)) r_exa" in subst)
      apply (rule_tac diff_comp_use_env)
     apply (rule_tac well_typed_diff_perms)
      apply (auto)
      apply (cut_tac env="env" and ?r_s1.0="r_s2a" and r_c="r_s1" and e="e2" and tau="tau" and ?r_s2.0="r_s2" and rx="rx1" in well_typed_incr_start_perm)
        apply (auto)
      apply (rule_tac well_typed_perm_leq)
      apply (auto)
    (* - lemma to prove non-prim x is not in e2 *)
     apply (cut_tac env="env" and ?r_s1.0="r_s1" and tau="tau" and ?r_s2.0="r_s2" and rx="rx1" and e="e2" and r_x="r_exa" in wtdep_strong_use_vars)
       apply (rule_tac ?r_s1.0="r_s2a" in well_typed_incr_start_perm)
        apply (auto)
     apply (rule_tac r_sb="norm_use_env r_s1 r_s2a" in trans_leq_use_env)
      apply (simp)
      apply (rule_tac id_leq_use_env)
     apply (rule_tac rhs_self_norm_leq_use_env)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    (* - second induction *)
    apply (rule_tac x="diff_use_env rx2 r_ex" in exI)
    apply (auto)
     apply (cut_tac r_x="r_s2" and r_s="r_s1" and r_xa="r_exa" and r_ex="r_ex" in wtdep_diff_use_env)
      apply (auto)
     apply (cut_tac r_x="rx2" and r_s="r_s1" and r_xa="r_exa" and r_ex="r_ex" in wtdep_diff_use_env)
      apply (auto)
      apply (rule_tac r_sb="r_s2" in trans_leq_use_env)
       apply (simp)
      apply (rule_tac well_typed_perm_leqx)
      apply (auto)
     apply (rule_tac t="diff_use_env rx2 (comp_use_env (diff_use_env r_ex r_exa) r_exa)" and s="diff_use_env (diff_use_env rx2 (diff_use_env r_ex r_exa)) r_exa" in subst)
      apply (rule_tac diff_comp_use_env)
     apply (rule_tac well_typed_diff_perms)
      apply (auto)
      apply (cut_tac env="env" and ?r_s1.0="r_s2a" and r_c="r_s1" and e="e3" and tau="tau" and ?r_s2.0="r_s2" and rx="rx2" in well_typed_incr_start_perm)
        apply (auto)
      apply (rule_tac well_typed_perm_leq)
      apply (auto)
    (* - lemma to prove non-prim x is not in e3 *)
     apply (cut_tac env="env" and ?r_s1.0="r_s1" and tau="tau" and ?r_s2.0="r_s2" and rx="rx2" and e="e3" and r_x="r_exa" in wtdep_strong_use_vars)
       apply (rule_tac ?r_s1.0="r_s2a" in well_typed_incr_start_perm)
        apply (auto)
     apply (rule_tac r_sb="norm_use_env r_s1 r_s2a" in trans_leq_use_env)
      apply (simp)
      apply (rule_tac id_leq_use_env)
     apply (rule_tac rhs_self_norm_leq_use_env)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    (* - final equality *)
    apply (simp add: diff_use_env_def)
    apply (rule_tac dist_minus_comp_use_env)
    (* the lambda case allows us to select any r_s2 + rx as long as they match. *)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
   apply (rule_tac x="comp_use_env r_exa r_ex" in exI)
   apply (auto)
      apply (rule_tac r_sb="diff_use_env (diff_use_env r_s1 r_exa) r_ex" in trans_leq_use_env)
       apply (rule_tac diff_comp_leq_use_env1)
      apply (rule_tac dist_diff_leq_use_env)
      apply (simp)
     apply (rule_tac dist_diff_leq_use_env)
     apply (simp)
    apply (rule_tac dist_comp_leq_use_env)
     apply (simp_all)
   apply (rule_tac lhs_unroll_dcl_use_env)
   apply (rule_tac dist_diff_leq_use_env)
   apply (simp)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="r_s2a" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (rule_tac x="r_s3" in exI)
  apply (auto)
  apply (rule_tac x="comp_use_env r_exa r_ex" in exI)
  apply (auto)
     apply (rule_tac rhs_unroll_dcl_use_env)
     apply (rule_tac rhs_unroll_dcl_use_env)
     apply (rule_tac dist_diff_leq_use_env)
     apply (rule_tac rhs_fold_dcl_use_env)
     apply (simp)
    apply (rule_tac dist_diff_leq_use_env)
    apply (simp)
   apply (rule_tac dist_comp_leq_use_env)
    apply (simp_all)
  apply (simp add: app_req_def)
  apply (auto)
   apply (rule_tac leq_empty_use_env)
  apply (rule_tac lhs_unroll_dcl_use_env)
  apply (rule_tac lhs_unroll_dcl_use_env)
  apply (rule_tac dist_diff_leq_use_env)
  apply (rule_tac lhs_fold_dcl_use_env)
  apply (simp)
  done

lemma well_typed_rem_end_perm: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; r_s1 x = OwnPerm \<rbrakk> \<Longrightarrow> well_typed env r_s1 e tau (rem_use_env r_s2 x) (rem_use_env rx x)"
  apply (cut_tac r_s="r_s2" and x="x" in diff_rem_use_env)
  apply (cut_tac r_s="rx" and x="x" in diff_rem_use_env)
  apply (auto)
  apply (rule_tac well_typed_diff_end_perm)
   apply (auto)
  apply (simp add: leq_use_env_def)
  apply (simp add: one_use_env_def)
  done

lemma well_typed_decr_end_perm: "\<lbrakk> well_typed env r_s1 e tau r_c rx; leq_use_env r_s2 r_c; leq_use_env rx r_s2 \<rbrakk> \<Longrightarrow> well_typed env r_s1 e tau r_s2 rx"
  apply (induction e arbitrary: env r_s1 tau rx)
        apply (auto)
        apply (rule_tac r_sb="r_c" in trans_leq_use_env)
         apply (auto)
       apply (rule_tac r_sb="r_c" in trans_leq_use_env)
        apply (auto)
      apply (rule_tac x="r_ex" in exI)
      apply (auto)
      apply (rule_tac r_sb="r_c" in trans_leq_use_env)
       apply (auto)
     apply (rule_tac x="r_s2a" in exI)
     apply (rule_tac x="r_s3" in exI)
     apply (rule_tac x="rx1" in exI)
     apply (auto)
     apply (rule_tac x="rx2" in exI)
     apply (auto)
     apply (rule_tac x="r_ex" in exI)
     apply (auto)
     apply (rule_tac r_sb="r_c" in trans_leq_use_env)
      apply (simp_all)
    apply (rule_tac x="rx'" in exI)
    apply (rule_tac x="r_s2a" in exI)
    apply (auto)
    apply (rule_tac x="rx1" in exI)
    apply (auto)
     apply (cut_tac r_sa="r_s2" and r_sb="comp_use_env rx1 rx2" and r_sc="rx1" in trans_leq_use_env)
       apply (auto)
     apply (rule_tac comp_leq_use_env1)
     apply (rule_tac id_leq_use_env)
    apply (rule_tac x="rx2" in exI)
    apply (auto)
    apply (cut_tac r_sa="r_s2" and r_sb="comp_use_env rx1 rx2" and r_sc="rx2" in trans_leq_use_env)
      apply (auto)
    apply (rule_tac comp_leq_use_env2)
    apply (rule_tac id_leq_use_env)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
   apply (rule_tac x="r_ex" in exI)
   apply (auto)
   apply (rule_tac r_sb="r_c" in trans_leq_use_env)
    apply (auto)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="r_s2a" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (rule_tac x="r_s3" in exI)
  apply (auto)
  apply (rule_tac x="r_ex" in exI)
  apply (auto)
  apply (rule_tac r_sb="r_c" in trans_leq_use_env)
   apply (auto)
  done

lemma well_typed_diff_decr_end_perm: "\<lbrakk> well_typed env r_s1 e tau (diff_use_env r_s2 r_ex) (diff_use_env rx r_ex');
    leq_use_env r_ex' r_ex; leq_use_env r_ex r_s1 \<rbrakk> \<Longrightarrow>
    well_typed env r_s1 e tau (diff_use_env r_s2 r_ex) (diff_use_env rx r_ex)"
  apply (case_tac "well_typed env r_s1 e tau (diff_use_env r_s2 r_ex) (diff_use_env rx r_ex) =
    well_typed env r_s1 e tau (diff_use_env (diff_use_env r_s2 r_ex) r_ex) (diff_use_env (diff_use_env rx r_ex') r_ex)")
   apply (simp)
   apply (rule_tac well_typed_diff_end_perm)
    apply (auto)
  apply (cut_tac r_s="r_s2" and r_x="r_ex" in double_diff_use_env)
  apply (cut_tac r_s="rx" and r_x="r_ex'" and r_c="r_ex" in cancel_diff_use_env)
   apply (auto)
  done

lemma well_typed_diff_decr_end_perm_gen: "\<lbrakk> well_typed env r_s1 e tau (diff_use_env r_s2 r_exb) (diff_use_env rx r_exb);
  leq_use_env r_exb r_exa; leq_use_env r_exa r_s1 \<rbrakk> \<Longrightarrow> well_typed env r_s1 e tau (diff_use_env r_s2 r_exa) (diff_use_env rx r_exa)"
  apply (cut_tac r_s="r_s2" and r_x="r_exb" and r_c="r_exa" in cancel_diff_use_env)
   apply (auto)
  apply (cut_tac r_s="rx" and r_x="r_exb" and r_c="r_exa" in cancel_diff_use_env)
   apply (auto)
  apply (rule_tac well_typed_diff_end_perm)
   apply (auto)
  done

    (*
      ####################################
        P9. well-typed manipulation for requirements
      ####################################
    *)

lemma well_typed_comp_req1: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; leq_use_env r_ex r_s2 \<rbrakk> \<Longrightarrow>
  well_typed env r_s1 e tau r_s2 (comp_use_env r_ex rx)"
  apply (induct e arbitrary: env r_s1 tau r_s2 rx r_ex)
        apply (auto)
    (* const + op case *)
        apply (rule_tac dist_comp_leq_use_env)
         apply (auto)
       apply (rule_tac dist_comp_leq_use_env)
        apply (auto)
    (* var cases *)
      apply (rule_tac x="r_exa" in exI)
      apply (auto)
       apply (rule_tac dist_comp_leq_use_env)
        apply (auto)
      apply (rule_tac comp_leq_use_env2)
      apply (simp)
    (* pair case *)
     apply (rule_tac x="r_s2a" in exI)
     apply (rule_tac x="r_s3" in exI)
     apply (rule_tac x="rx1" in exI)
     apply (auto)
     apply (rule_tac x="rx2" in exI)
     apply (auto)
     apply (rule_tac x="r_exa" in exI)
     apply (auto)
      apply (rule_tac dist_comp_leq_use_env)
       apply (simp_all)
     apply (rule_tac comp_leq_use_env2)
     apply (simp)
    (* if case *)
    apply (rule_tac x="rx'" in exI)
    apply (rule_tac x="r_s2a" in exI)
    apply (auto)
    apply (rule_tac x="comp_use_env r_ex rx1" in exI)
    apply (auto)
    apply (rule_tac x="rx2" in exI)
    apply (auto)
    apply (rule_tac assoc_comp_use_env)
    (* lambda case *)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
   apply (rule_tac x="r_exa" in exI)
   apply (auto)
    apply (rule_tac dist_comp_leq_use_env)
     apply (auto)
   apply (rule_tac comp_leq_use_env2)
   apply (simp)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="r_s2a" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (rule_tac x="r_s3" in exI)
  apply (auto)
  apply (rule_tac x="r_exa" in exI)
  apply (auto)
   apply (rule_tac dist_comp_leq_use_env)
    apply (auto)
  apply (rule_tac comp_leq_use_env2)
  apply (simp)
  done

lemma well_typed_comp_req2: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; leq_use_env r_ex r_s2 \<rbrakk> \<Longrightarrow>
  well_typed env r_s1 e tau r_s2 (comp_use_env rx r_ex)"
  apply (cut_tac r_s="rx" and r_x="r_ex" in comm_comp_use_env)
  apply (auto)
  apply (rule_tac well_typed_comp_req1)
   apply (auto)
  done

lemma well_typed_incr_req: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; leq_use_env rx rc; leq_use_env rc r_s2 \<rbrakk> \<Longrightarrow> well_typed env r_s1 e tau r_s2 rc"
  apply (induct e arbitrary: env r_s1 tau r_s2 rx)
        apply (auto)
    (* var case *)
      apply (rule_tac x="r_ex" in exI)
      apply (auto)
      apply (rule_tac r_sb="rx" in trans_leq_use_env)
       apply (auto)
    (* pair case *)
     apply (rule_tac x="r_s2a" in exI)
     apply (rule_tac x="r_s3" in exI)
     apply (rule_tac x="rx1" in exI)
     apply (auto)
     apply (rule_tac x="rx2" in exI)
     apply (auto)
     apply (rule_tac x="r_ex" in exI)
     apply (auto)
     apply (rule_tac r_sb="rx" in trans_leq_use_env)
      apply (auto)
    (* if case *)
    apply (rule_tac x="rx'" in exI)
    apply (rule_tac x="r_s2a" in exI)
    apply (auto)
    apply (rule_tac x="rc" in exI)
    apply (auto)
     apply (cut_tac r_sc="rx1" and r_sb="comp_use_env rx1 rx2" and r_sa="rc" in trans_leq_use_env)
       apply (simp)
      apply (rule_tac self_comp_leq_use_env1)
     apply (simp)
    apply (rule_tac x="rc" in exI)
    apply (auto)
     apply (cut_tac r_sc="rx2" and r_sb="comp_use_env rx1 rx2" and r_sa="rc" in trans_leq_use_env)
       apply (simp)
      apply (rule_tac self_comp_leq_use_env2)
     apply (simp)
    apply (case_tac "\<forall> x. rc x = comp_use_env rc rc x")
     apply (auto)
    apply (simp add: comp_use_env_def)
    apply (case_tac "rc x")
      apply (auto)
    (* lam case *)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
   apply (rule_tac x="r_ex" in exI)
   apply (auto)
   apply (rule_tac r_sb="rx" in trans_leq_use_env)
    apply (auto)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="r_s2a" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (rule_tac x="r_s3" in exI)
  apply (auto)
  apply (rule_tac x="r_ex" in exI)
  apply (auto)
  apply (rule_tac r_sb="rx" in trans_leq_use_env)
   apply (auto)
  done

lemma well_typed_simul_end_perm: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; leq_use_env r_c r_s2;
  leq_use_env rc r_c; leq_use_env rx rc \<rbrakk> \<Longrightarrow> well_typed env r_s1 e tau r_c rc"
  apply (rule_tac rx="rx" in well_typed_incr_req)
    apply (rule_tac r_c="r_s2" in well_typed_decr_end_perm)
      apply (auto)
  apply (rule_tac r_sb="rc" in trans_leq_use_env)
   apply (auto)
  done
    (*
lemma well_typed_add_perms2: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; x \<notin> non_prim_vars env e \<rbrakk> \<Longrightarrow>
  well_typed env (add_use_env r_s1 x r) e tau (add_use_env r_s2 x r) rx"
  apply (rule_tac rx="rem_use_env rx x" in well_typed_incr_req)
    apply (cut_tac r_s="r_s1" and x="x" and r="r" in partial_add_rem_use_env)
    apply (cut_tac r_s="r_s2" and x="x" and r="r" in partial_add_rem_use_env)
    apply (cut_tac r_s="rem_use_env r_s1 x" and x="x" and r="r" in add_comp_use_env)
     apply (auto)
     apply (simp add: rem_use_env_def)
    apply (cut_tac r_s="rem_use_env r_s2 x" and x="x" and r="r" in add_comp_use_env)
     apply (auto)
     apply (simp add: rem_use_env_def)
    apply (rule_tac well_typed_comp_perms)
     apply (rule_tac well_typed_rem_perms)
      apply (auto)
    apply (simp add: disj_use_env_def)
    apply (simp add: one_use_env_def)
    apply (simp add: rem_use_env_def)
   apply (cut_tac env="env" and ?r_s1.0="r_s1" and e="e" and tau="tau" and ?r_s2.0="r_s2" and rx="rx" and x="x" in well_typed_rem_perms)
     apply (auto)
  done   *)

lemma well_typed_add_permsx: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; x \<notin> non_prim_vars env e \<rbrakk> \<Longrightarrow>
  well_typed env (add_use_env r_s1 x r) e tau (add_use_env r_s2 x r) (add_use_env rx x r)"
  apply (cut_tac r_s="r_s1" and x="x" and r="r" in partial_add_rem_use_env)
  apply (cut_tac r_s="r_s2" and x="x" and r="r" in partial_add_rem_use_env)
  apply (cut_tac r_s="rx" and x="x" and r="r" in partial_add_rem_use_env)
  apply (simp)
  apply (cut_tac r_s="rem_use_env r_s1 x" and x="x" and r="r" in add_comp_use_env)
   apply (auto)
   apply (simp add: rem_use_env_def)
  apply (cut_tac r_s="rem_use_env r_s2 x" and x="x" and r="r" in add_comp_use_env)
   apply (auto)
   apply (simp add: rem_use_env_def)
  apply (cut_tac r_s="rem_use_env rx x" and x="x" and r="r" in add_comp_use_env)
   apply (auto)
   apply (simp add: rem_use_env_def)
  apply (rule_tac well_typed_comp_req2)
   apply (rule_tac well_typed_comp_perms)
    apply (rule_tac well_typed_rem_perms)
     apply (auto)
   apply (simp add: disj_use_env_def)
   apply (simp add: mini_disj_use_env_def)
   apply (simp add: one_use_env_def)
   apply (simp add: rem_use_env_def)
  apply (rule_tac self_comp_leq_use_env2)
  done

    (*
      ####################################
        P10. well-typed manipulation involving lifts
      ####################################
    *)

lemma well_typed_lift_req: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; leq_use_env (lift_use_env rx r) r_s2 \<rbrakk> \<Longrightarrow> well_typed env r_s1 e tau r_s2 (lift_use_env rx r)"
  apply (induct e arbitrary: env r_s1 tau r_s2 rx)
        apply (auto)
    (* var case *)
      apply (rule_tac x="r_ex" in exI)
      apply (auto)
      apply (rule_tac lift_leq_use_env)
      apply (simp)
    (* pair case *)
     apply (rule_tac x="r_s2a" in exI)
     apply (rule_tac x="r_s3" in exI)
     apply (rule_tac x="rx1" in exI)
     apply (auto)
     apply (rule_tac x="rx2" in exI)
     apply (auto)
     apply (rule_tac x="r_ex" in exI)
     apply (auto)
     apply (rule_tac lift_leq_use_env)
     apply (simp)
    (* if case *)
    apply (rule_tac x="rx'" in exI)
    apply (rule_tac x="r_s2a" in exI)
    apply (auto)
    apply (rule_tac x="lift_use_env rx1 r" in exI)
    apply (auto)
     apply (cut_tac r_sc="lift_use_env rx1 r" and r_sb="lift_use_env (comp_use_env rx1 rx2) r" and r_sa="r_s2" in trans_leq_use_env)
       apply (simp)
      apply (rule_tac dist_lift_leq_use_env)
      apply (rule_tac self_comp_leq_use_env1)
     apply (auto)
    apply (rule_tac x="lift_use_env rx2 r" in exI)
    apply (auto)
     apply (cut_tac r_sc="lift_use_env rx2 r" and r_sb="lift_use_env (comp_use_env rx1 rx2) r" and r_sa="r_s2" in trans_leq_use_env)
       apply (simp)
      apply (rule_tac dist_lift_leq_use_env)
      apply (rule_tac self_comp_leq_use_env2)
     apply (auto)
    apply (rule_tac lift_comp_use_env)
    (* lam case *)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
   apply (rule_tac x="r_ex" in exI)
   apply (auto)
   apply (rule_tac lift_leq_use_env)
   apply (simp)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="ra" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="r_s2a" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (auto)
  apply (rule_tac x="r_s3" in exI)
  apply (auto)
  apply (rule_tac x="r_ex" in exI)
  apply (auto)
  apply (rule_tac lift_leq_use_env)
  apply (auto)
  done

lemma well_typed_lift_all_perms: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx \<rbrakk> \<Longrightarrow> well_typed env (lift_use_env r_s1 r) e tau (lift_use_env r_s2 r) (lift_use_env rx r)"
  apply (rule_tac well_typed_lift_req)
   apply (rule_tac well_typed_lift_perms)
   apply (simp)
  apply (rule_tac dist_lift_leq_use_env)
  apply (rule_tac well_typed_perm_leqx)
  apply (auto)
  done

end