Theory CheckerExe


theory CheckerExe
  imports TheoryExe ProofTerm
begin

abbreviation "exetyp_ok Θ  exetyp_ok_sig (exesig Θ)"

lemma typ_ok_code: 
  assumes "exe_wf_theory' Θ"
  shows "typ_ok (translate_theory Θ) ty = exetyp_ok Θ ty"
  using assms typ_ok_sig_code
  by (metis exe_sig_conds_def exe_wf_theory.simps exe_wf_theory_code exesignature.exhaust
      exetheory.sel(1) sig.simps translate_theory.elims typ_ok_def wf_type_iff_typ_ok_sig)

definition [simp]: "execlass_leq cs c1 c2 = List.member cs (c1,c2)"
lemma execlass_leq_code: "class_leq (set cs) c1 c2 = execlass_leq cs c1 c2"
  by (simp add: class_leq_def class_les_def member_def)

definition "exesort_leq sub s1 s2 = (c2  s2 . c1  s1. execlass_leq sub c1 c2)"
lemma exesort_les_code: "sort_leq (set cs) c1 c2 = exesort_leq cs c1 c2"
  by (simp add: execlass_leq_code exesort_leq_def sort_leq_def)

fun exehas_sort :: "exeosig  typ  sort  bool" where
"exehas_sort oss (Tv _ S) S' = exesort_leq (execlasses oss) S S'" |
"exehas_sort oss (Ty a Ts) S =
  (case lookup (λk. k=a) (exetcsigs oss) of
  None  False |
  Some mgd  (C  S.
    case lookup (λk. k=C) mgd of
        None  False
      | Some Ss  list_all2 (exehas_sort oss) Ts Ss))"

(* cleanup *)
lemma exehas_sort_imp_has_sort: 
  assumes "exe_osig_conds (sub, tcs)"
  shows "exehas_sort (sub, tcs) T S  has_sort (translate_osig (sub, tcs)) T S"
proof (induction T arbitrary: S)
  case (Ty n Ts)
  obtain sub' tcs' where sub'_tcs': "translate_osig (sub, tcs) = (sub', tcs')" by fastforce
  obtain mgd where mgd: "tcs' n = Some mgd" 
    using Ty.prems sub'_tcs' apply (simp split: option.splits) 
    by (metis assms exe_ars_conds_def exe_osig_conds_def in_alist_imp_in_map_of lookup_eq_map_of_ap 
        map_of_SomeD snd_conv)
  show ?case
  proof (subst sub'_tcs', rule has_sort_Ty[of tcs', OF mgd], rule ballI)
    fix c assume asm: "cS"

    have l: "lookup (λk. k=n) (map (apsnd map_of) tcs) = Some mgd"
      by (metis assms lookup_eq_map_of_ap mgd snd_conv sub'_tcs' translate_ars.simps translate_osig.simps)
    hence "x. (lookup (λk. k=n) tcs) = Some x"
      by (induction tcs) auto
    from this obtain pre_mgd where pre_mgd: "(lookup (λk. k=n) tcs) = Some pre_mgd"
      by blast
    have pre_mgd_mgd: "map_of pre_mgd = mgd"
      by (metis l assms exe_ars_conds_def
          exe_osig_conds_def in_alist_imp_in_map_of lookup_eq_map_of_ap map_of_SomeD 
          option.sel pre_mgd snd_conv translate_ars.simps)

    obtain Ss where Ss: "lookup (λk. k=c) pre_mgd = Some Ss"
      using Ty.prems asm by (auto simp add: pre_mgd split: option.splits)
    hence cond: "list_all2 (exehas_sort (sub,tcs)) Ts Ss"
      using exehas_sort (sub, tcs) (Ty n Ts) Sasm pre_mgd by (auto split: option.splits)
      
    from Ss have "mgd c = Some Ss"
      by (simp add: lookup_eq_map_of_ap pre_mgd_mgd)
    then show "Ss. mgd c = Some Ss  list_all2 (has_sort (sub', tcs')) Ts Ss"
      using cond Ty.IH list.rel_mono_strong sub'_tcs' by force
  qed
next
  case (Tv n S)
  then show ?case
    by (metis assms exehas_sort.simps(1) exesort_les_code has_sort_Tv prod.collapse translate_osig.simps)
qed

lemma has_sort_imp_exehas_sort: 
  assumes "exe_osig_conds (sub, tcs)"
  shows "has_sort (translate_osig (sub, tcs)) T S  exehas_sort (sub, tcs) T S"
proof (induction T arbitrary: S)
  case (Ty n Ts)
  obtain sub' tcs' where sub'_tcs': "translate_osig (sub, tcs) = (sub', tcs')" by fastforce
  obtain mgd where mgd: "tcs' n = Some mgd" 
    using Ty.prems sub'_tcs' has_sort.simps by (auto split: option.splits)
  hence "lookup (λk. k=n) (map (apsnd map_of) tcs) = Some mgd"
    by (metis assms lookup_eq_map_of_ap prod.inject sub'_tcs' translate_ars.simps translate_osig.simps)
  have l: "lookup (λk. k=n) (map (apsnd map_of) tcs) = Some mgd"
    by (metis assms lookup_eq_map_of_ap mgd snd_conv sub'_tcs' 
        translate_ars.simps translate_osig.simps)
  hence "x. (lookup (λk. k=n) tcs) = Some x"
    by (induction tcs) auto
  from this obtain pre_mgd where pre_mgd: "(lookup (λk. k=n) tcs) = Some pre_mgd"
    by blast
  have pre_mgd_mgd: "map_of pre_mgd = mgd"
    by (metis l assms exe_ars_conds_def
        exe_osig_conds_def in_alist_imp_in_map_of lookup_eq_map_of_ap map_of_SomeD option.sel
        pre_mgd snd_conv translate_ars.simps)

  {
    fix c assume asm: "cS"
    
    obtain Ss where Ss: "lookup (λk. k=c) pre_mgd = Some Ss"
      using c  S map_of pre_mgd = mgd sub'_tcs' mgd assms Ty.prems has_sort.simps
      by (auto simp add: dom_map_of_conv_image_fst domIff eq_fst_iff exe_ars_conds_def 
          map_of_eq_None_iff classes_translate lookup_eq_map_of_ap split: typ.splits
          dest!: domD intro!: domI)
    have l: "length Ts = length Ss"
      using asm mgd pre_mgd Ty.prems assms sub'_tcs' Ss list_all2_lengthD pre_mgd_mgd
      by (fastforce simp add: has_sort.simps lookup_eq_map_of_ap)

    have 1: "c  S. Ss . mgd c = Some Ss  list_all2 (has_sort (sub', tcs')) Ts Ss"
      using mgd Ty.prems has_sort.simps sub'_tcs' by auto

    have cond: "list_all2 (exehas_sort (sub,tcs)) Ts Ss"
      apply (rule list_all2_all_nthI)
      using l apply simp
      subgoal premises p for m 
        apply (rule Ty.IH)
        using p apply simp
        using p Ty.prems assms 1
        by (metis Ss asm list_all2_conv_all_nth lookup_eq_map_of_ap option.sel pre_mgd_mgd sub'_tcs') 
      done
    have "(C  S.
    case lookup (λk. k=C) pre_mgd of
        None  False
      | Some Ss  list_all2 (exehas_sort (sub,tcs)) Ts Ss)"
      by (metis "1" Ty.IH list_all2_conv_all_nth lookup_eq_map_of_ap nth_mem option.simps(5) 
        pre_mgd_mgd sub'_tcs')
  }

  then show ?case
    using pre_mgd by simp
next
  case (Tv n S)
  then show ?case
    using assms exesort_les_code has_sort_Tv_imp_sort_leq by fastforce
qed

lemma has_sort_code:
  assumes "exe_osig_conds oss"
  shows "has_sort (translate_osig oss) T S = exehas_sort oss T S"
  by (metis assms exehas_sort_imp_has_sort has_sort_imp_exehas_sort prod.collapse)

lemma has_sort_code':
  assumes "exe_wf_theory' Θ"
  shows "has_sort (osig (sig (translate_theory Θ))) T S 
    = exehas_sort (exesorts (exesig Θ)) T S"
  apply (cases Θ rule: exetheory_full_exhaust) using assms has_sort_code by auto

abbreviation "exeinst_ok Θ insts  
    distinct (map fst insts)
   list_all (exetyp_ok Θ) (map snd insts)
   list_all (λ((idn, S), T) . exehas_sort (exesorts (exesig Θ)) T S) insts"

lemma inst_ok_code1:
  assumes "exe_wf_theory' Θ"
  shows "list_all (exetyp_ok Θ) (map snd insts) = list_all (typ_ok (translate_theory Θ)) (map snd insts)"
  using assms typ_ok_code by (auto simp add: list_all_iff)

lemma inst_ok_code2:
  assumes "exe_wf_theory' Θ"
  shows "list_all (λ((idn, S), T) . has_sort (osig (sig (translate_theory Θ))) T S) insts
    = list_all (λ((idn, S), T) . exehas_sort (exesorts (exesig Θ)) T S) insts"
  using has_sort_code' assms by auto

lemma inst_ok_code:
  assumes "exe_wf_theory' Θ"
  shows "inst_ok (translate_theory Θ) insts = exeinst_ok Θ insts"
  using inst_ok_code1 inst_ok_code2 assms by auto

definition [simp]: "exeterm_ok Θ t  exeterm_ok' (exesig Θ) t  typ_of t  None"
lemma term_ok_code:
  assumes "exe_wf_theory' Θ"
  shows "term_ok (translate_theory Θ) t = exeterm_ok Θ t"
  using assms apply (cases Θ rule: exetheory_full_exhaust) 
  by (metis exe_sig_conds_def exe_wf_theory'.simps exeterm_ok_def exetheory.sel(1) 
      sig.simps term_okD1 term_okD2 term_okI wt_term_code translate_theory.simps)

fun exereplay' :: "exetheory  (variable × typ) list  variable set
   term list  proofterm  term option" where
  "exereplay' thy _ _ Hs (PAxm t Tis) = (if exeinst_ok thy Tis  exeterm_ok thy t
    then if t  set (exeaxioms_of thy)
      then Some (forall_intro_vars (subst_typ' Tis t) []) 
    else None else None)"
| "exereplay' thy _ _ Hs (PBound n) = partial_nth Hs n" 
| "exereplay' thy vs ns Hs (Abst T p) = (if exetyp_ok thy T 
    then (let (s',ns') = variant_variable (Free STR ''default'') ns in 
      map_option (mk_all s' T) (exereplay' thy ((s', T) # vs) ns' Hs p))
    else None)"
| "exereplay' thy vs ns Hs (Appt p t) = 
    (let rep = exereplay' thy vs ns Hs p in
    let t' = subst_bvs (map (λ(x,y) . Fv x y) vs) t in
      case (rep, typ_of t') of
        (Some (Ct s (Ty fun1 [Ty fun2 [τ, Ty propT1 Nil], Ty propT2 Nil]) $ b), Some τ')  
          if s = STR ''Pure.all''  fun1 = STR ''fun''  fun2 = STR ''fun'' 
             propT1 = STR ''prop''  propT2 = STR ''prop''
              τ=τ'  exeterm_ok thy t'
            then Some (b  t') else None
      | _  None)" 
| "exereplay' thy vs ns Hs (AbsP t p) =
    (let t' = subst_bvs (map (λ(x,y) . Fv x y) vs) t in
    let rep = exereplay' thy vs ns (t'#Hs) p in
      (if typ_of t' = Some propT  exeterm_ok thy t' then map_option (mk_imp t') rep else None))"
| "exereplay' thy vs ns Hs (AppP p1 p2) = 
    (let rep1 = Option.bind (exereplay' thy vs ns Hs p1) beta_eta_norm in
    let rep2 = Option.bind (exereplay' thy vs ns Hs p2) beta_eta_norm in
      (case (rep1, rep2) of (
        Some (Ct imp (Ty fn1 [Ty prp1 [], Ty fn2 [Ty prp2 [], Ty prp3 []]]) $ A $ B),
        Some A')  
          if imp = STR ''Pure.imp''  fn1 = STR ''fun''  fn2 = STR ''fun''
             prp1 = STR ''prop''  prp2 = STR ''prop''  prp3 = STR ''prop''  A=A' 
          then Some B else None
        | _  None))"
| "exereplay' thy vs ns Hs (OfClass ty c) = (if exehas_sort (exesorts (exesig thy)) ty {c} 
     exetyp_ok thy ty
    then (case lookup (λk. k=const_of_class c) (execonst_type_of (exesig thy)) of 
      Some (Ty fun [Ty it [ity], Ty prop []])  
        if ity = tvariable STR '''a''  fun = STR ''fun''  prop = STR ''prop''  it = STR ''itself''
          then Some (mk_of_class ty c) else None | _  None) else None)"
| "exereplay' thy vs ns Hs (Hyp t) = (if tset Hs then Some t else None)"

lemma of_class_code1: 
  assumes "exe_wf_theory' thy"
  shows "(has_sort (osig (sig (translate_theory thy))) ty {c}  typ_ok (translate_theory thy) ty)
    = (exehas_sort (exesorts (exesig thy)) ty {c}  exetyp_ok thy ty)"
proof-
  have "has_sort (osig (sig (translate_theory thy))) ty {c}
    = exehas_sort (exesorts (exesig thy)) ty {c}"
    using has_sort_code' assms by simp
  moreover have "typ_ok (translate_theory thy) ty = exetyp_ok thy ty"
    using typ_ok_code assms by simp
  ultimately show ?thesis 
    by auto
qed

lemma of_class_code2: 
  assumes "exe_wf_theory' thy"
  shows "const_type (sig (translate_theory thy)) (const_of_class c) 
    = lookup (λk. k=const_of_class c) (execonst_type_of (exesig thy))"
  by (metis assms const_type_of_lookup_code exe_wf_theory_code 
      exe_wf_theory_translate_imp_wf_theory exetheory.sel(1) illformed_theory_not_wf_theory 
      sig.simps translate_theory.elims)

lemma replay'_code:
  assumes "exe_wf_theory' thy"
  shows "replay' (translate_theory thy) vs ns Hs P = exereplay' thy vs ns Hs P"
proof (induction P arbitrary: vs ns Hs)
  case (PAxm ax tys)
  have wf: "wf_theory (translate_theory thy)"
    by (simp add: assms exe_wf_theory_code exe_wf_theory_translate_imp_wf_theory)
  moreover have inst: "inst_ok (translate_theory thy) tys  exeinst_ok thy tys"
    by (simp add: assms inst_ok_code1 inst_ok_code2)
  moreover have tok: "term_ok (translate_theory thy) ax  exeterm_ok thy ax"
    using assms term_ok_code by blast
  moreover have ax: "ax  axioms (translate_theory thy)  ax  set (exeaxioms_of thy)"
    by (metis axioms.simps wf exetheory.sel(2) illformed_theory_not_wf_theory translate_theory.elims)
  ultimately show ?case
    by simp
qed (use assms term_ok_code typ_ok_code of_class_code1 of_class_code2 
      in auto simp only: replay'.simps exereplay'.simps split: if_splits)

abbreviation "exereplay'' thy vs ns Hs P  Option.bind (exereplay' thy vs ns Hs P) beta_eta_norm"
lemma replay''_code:
  assumes "exe_wf_theory' thy"
  shows "replay'' (translate_theory thy) vs ns Hs P = exereplay'' thy vs ns Hs P"
  by (simp add: assms replay'_code)

definition [simp]: "exereplay thy P  
  (if xset (hyps P) . exeterm_ok thy x  typ_of x = Some propT then
  exereplay'' thy [] (fst ` (fv_Proof P  FV (set (hyps P)))) (hyps P) P else None)"

lemma replay_code:
  assumes "exe_wf_theory' thy"
  shows "replay (translate_theory thy) P = exereplay thy P"
  using assms replay''_code term_ok_code by auto

definition "exe_replay' e P = exereplay'' e [] (fst ` fv_Proof P) [] P"

definition "exe_check_proof e P res  
  exe_wf_theory' e  exereplay e P = Some res"

lemma exe_check_proof_iff_check_proof: 
  "exe_check_proof e P res  check_proof (translate_theory e) P res"
  using check_proof_def exe_check_proof_def wf_theory_translate_iff_exe_wf_theory 
  by (metis exe_wf_theory_code replay_code)

lemma check_proof_sound:
  shows "exe_check_proof e P res  translate_theory e, set (hyps P)  res"
  by (simp add: check_proof_sound exe_check_proof_iff_check_proof)

lemma check_proof_really_sound:
  shows "exe_check_proof e P res  translate_theory e, set (hyps P)  res"
  by (simp add: check_proof_really_sound exe_check_proof_iff_check_proof)

end